Конфликт между типом = PersistenceContextType.EXTENDED и javax.persistence.OptimisticLockException в приложении JSF / Spring / JPA / Hibernate - PullRequest
0 голосов
/ 02 марта 2012

Я пытаюсь перенести чистое веб-приложение JSF / Hibernate на приложение JSF / Spring 3.0 / Hibernate / JPA.Я использую зависимость, чтобы внедрить экземпляр EntityManager в мой класс DAO.Если я использую атрибут type = PersistenceContextType.EXTENDED в аннотации @PersistenceContext, это состояние является общим для всех браузеров, и страница входа в систему не отображается.Я пробовал разные браузеры, а не просто разные окна, например JSF - бин области сеанса, совместно используемый браузерами на разных машинах Если я не укажу EXTENDED, я не смогу обновить свои записи после первого обновления и получить javax.persistence.OptimisticLockException

Недавно я узнал о том, что называется View scope, но не уверен, является ли это решением.Пожалуйста, предложите способ достижения обеих целей а.Избегайте OptimisticLockException при последующих обновлениях b.Избегайте совместного использования состояния между браузерами

Спасибо Сагар Р. Кападиа

Мои файлы конфигурации и исходные файлы выглядят следующим образом

DataSource.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

 <bean 
   class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
   <property name="location">
     <value>WEB-INF/classes/config/database/db.properties</value>
   </property>
</bean>

  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" >
    <property name="driverClass" value="${jdbc.driverClassName}" />
    <property name="jdbcUrl" value="${jdbc.url}" />
    <property name="user" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
  </bean>

</beans>

HibernateSessionFactory.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<!-- Hibernate session factory -->
<bean id="sessionFactory" 
     class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >

    <property name="dataSource">
      <ref bean="dataSource"/>
    </property>

    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialect</prop>

            <prop key="transaction.factory_class">
                net.sf.hibernate.transaction.JDBCTransactionFactory
            </prop>
            <!-- 
            <prop key="hibernate.transaction.factory_class">
                net.sf.hibernate.transaction.JDBCTransactionFactory
            </prop>
             -->
            <prop key="hibernate.show_sql">false</prop>
            <prop key="hibernate.cglib.use_reflection_optimizer">false</prop>
            <prop key="hibernate.jdbc.batch_size">0</prop>

            <prop key="hibernate.c3p0.min_size" >2</prop>
            <prop key="hibernate.c3p0.max_size"> 5</prop>
            <prop key="hibernate.c3p0.timeout">600</prop>
            <prop key="hibernate.c3p0.max_statements">0</prop>
            <prop key="hibernate.c3p0.idle_test_period" >300</prop>
            <prop key="hibernate.c3p0.acquire_increment">1</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
           <prop key="hibernate.show_sql">true</prop>
       </props>
    </property>

    <property name="mappingResources">
    <list>  
        <value>com/compucloud/galleryadmin/entity/Period.hbm.xml</value>
        <value>com/compucloud/galleryadmin/entity/ApplicationUser.hbm.xml</value>
        <value>com/compucloud/galleryadmin/entity/Device.hbm.xml</value>
        <value>com/compucloud/galleryadmin/entity/Deal.hbm.xml</value>
        <value>com/compucloud/galleryadmin/entity/ComboDealItem.hbm.xml</value>
        <value>com/compucloud/galleryadmin/entity/City.hbm.xml</value>
        <value>com/compucloud/galleryadmin/entity/DiscountDeal.hbm.xml</value>
        <value>com/compucloud/galleryadmin/entity/State.hbm.xml</value>
        <value>com/compucloud/galleryadmin/entity/FreeDeal.hbm.xml</value>
        <value>com/compucloud/galleryadmin/entity/OrderDetail.hbm.xml</value>
        <value>com/compucloud/galleryadmin/entity/Product.hbm.xml</value>
        <value>com/compucloud/galleryadmin/entity/Country.hbm.xml</value>
        <value>com/compucloud/galleryadmin/entity/Category.hbm.xml</value>
        <value>com/compucloud/galleryadmin/entity/Administrator.hbm.xml</value>
        <value>com/compucloud/galleryadmin/entity/Company.hbm.xml</value>
        <value>com/compucloud/galleryadmin/entity/ComboDeal.hbm.xml</value>
        <value>com/compucloud/galleryadmin/entity/Order.hbm.xml</value>
    </list>
     </property>    

</bean>
</beans>

face-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<faces-config
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
    version="2.0">

    <application>
        <el-resolver>
            org.springframework.web.jsf.el.SpringBeanFacesELResolver
        </el-resolver>
         <variable-resolver>
            org.springframework.web.jsf.DelegatingVariableResolver
        </variable-resolver>

    </application>
<!--Navigation rules omitted-->
</faces-config>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
    id="WebApp_ID" version="2.5">

  <display-name>HelloJSF</display-name>

  <!-- Add Support for Spring -->
  <listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
  </listener>
  <listener>
    <listener-class>
        org.springframework.web.context.request.RequestContextListener
    </listener-class>
  </listener>

  <!-- Change to "Production" when you are ready to deploy -->
  <context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
  </context-param>

  <!-- Welcome page -->
  <welcome-file-list>
    <welcome-file>faces/login.xhtml</welcome-file>
  </welcome-file-list>

  <!-- JSF mapping -->
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <!-- Map these files with JSF -->
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.jsf</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.faces</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
  </servlet-mapping>



 <filter>
    <filter-name>Extensions Filter</filter-name>
    <filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>Extensions Filter</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

</web-app>

applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:lang="http://www.springframework.org/schema/lang"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

 <aop:aspectj-autoproxy proxy-target-class="true"/>
 <context:component-scan base-package="com.compucloud.galleryadmin" />

 <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="database" value="MYSQL"></property>
        <property name="showSql" value="true"></property>
        <property name="generateDdl" value="false"></property>
        <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"></property>
    </bean>



    <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
        <property name="dataSource" ref="dataSource"></property>
        <property name="jpaVendorAdapter" ref="jpaVendorAdapter"></property>

    </bean>
    <!-- 
    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor">

    </bean>
    <tx:annotation-driven />
    -->
    <tx:annotation-driven transaction-manager="demoTxManager"/>
    <context:component-scan base-package="com.compucloud.galleryadmin" />
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"></bean>


    <bean id="demoTxManager" class="org.springframework.orm.jpa.JpaTransactionManager" >
        <property name="entityManagerFactory" ref="emf" />
    </bean>

    <aop:config>
        <aop:pointcut id="jpaDaoMethods" 
            expression="execution(* com.compucloud.galleryadmin.databaseutil.Database.*.*(..))" />
        <aop:advisor advice-ref="demoTxAdvice" pointcut-ref="jpaDaoMethods" />
    </aop:config>

    <tx:advice id="demoTxAdvice" transaction-manager="demoTxManager" >
    <!-- 
        <tx:attributes>
            <tx:method name="persist*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="reset*" propagation="SUPPORTS" />
            <tx:method name="load*" propagation="SUPPORTS" read-only="true" />


        </tx:attributes>
         -->
    </tx:advice>

        <!-- 
            <tx:method name="retrieve*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="query*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="find*" propagation="SUPPORTS" read-only="false" />
             -->


    <!-- Database Configuration -->
    <import resource="classes/config/spring/beans/DataSource.xml"/>
    <import resource="classes/config/spring/beans/HibernateSessionFactory.xml"/>



    <bean id="database" class="com.compucloud.galleryadmin.databaseutil.Database" scope="session" ></bean>

    <bean id="country" class="com.compucloud.galleryadmin.entity.Country" scope="request"></bean>
    <bean id="state" class="com.compucloud.galleryadmin.entity.State" scope="request"></bean>
    <bean id="city" class="com.compucloud.galleryadmin.entity.City" scope="request"></bean>
    <bean id="administrator" class="com.compucloud.galleryadmin.entity.Administrator" scope="request" ></bean>
    <bean id="companyAdministrator" class="com.compucloud.galleryadmin.entity.Administrator" scope="request"></bean>
    <bean id="currentAdministrator" class="com.compucloud.galleryadmin.entity.Administrator" scope="session"></bean>
    <bean id="currentCompany" class="com.compucloud.galleryadmin.entity.Company" scope="session"></bean>
    <bean id="company" class="com.compucloud.galleryadmin.entity.Company" scope="request" ></bean>
    <bean id="category" class="com.compucloud.galleryadmin.entity.Category" scope="request"></bean>
    <bean id="product" class="com.compucloud.galleryadmin.entity.Product" scope="request"></bean>
    <bean id="deal" class="com.compucloud.galleryadmin.entity.Deal" scope="request" ></bean>
    <bean id="discountDeal" class="com.compucloud.galleryadmin.entity.DiscountDeal" scope="request" ></bean>
    <bean id="freeDeal" class="com.compucloud.galleryadmin.entity.FreeDeal" scope="request"></bean>
    <bean id="comboDeal" class="com.compucloud.galleryadmin.entity.ComboDeal" scope="request"></bean>

</beans>

База данных.Ява

@Repository
@Transactional

public class Database  implements Serializable{

    @PersistenceContext()
    private EntityManager em;


    private Exception lastException;
    private Category category;
    private Country country;  
    private State state;
    private City city;
    private Administrator administrator;
    private Administrator companyAdministrator;
    private Administrator currentAdministrator;
    private Company company;
    private Company currentCompany;
    private Deal deal;
    private DiscountDeal discountDeal;
    private FreeDeal freeDeal;
    private ComboDeal comboDeal;

    //private Deal currentDeal;
    private List<Company>listOfCompanies;
    private List<Country>listOfCountries;
    private List<State>listOfStates;
    private List<City>listOfCities;
    private List<Administrator>listOfAdministrators;
    private List<Administrator>listOfCompanyAdministrators;
    private List<Category> listOfCategories;
    private List<Category> listOfChildCategories;
    private Category currentCategory;
    private Product product;
    private Product productForComboDeal;

    private List<Product>listOfProducts;


    private List<Deal> listOfDeals;
    private List<DiscountDeal> listOfDiscountDeals;
    private List<FreeDeal> listOfFreeDeals;
    private List<ComboDeal> listOfComboDeals;
    /*
    private Session m_Session;
    private SessionFactory sessionFactory;
    */
    /*
    private UploadedFile uploadedFileCategory;
    private UploadedFile uploadedFileProduct;
    private UploadedFile uploadedFileProductLarge;*/

    public Database(){

    }
    public void persistWithUpdatedFlag(Object obj){
        obj=em.merge(obj);
        em.flush();
        refreshBeans(obj);
        }

//Other Methods omitted
}

1 Ответ

1 голос
/ 02 марта 2012

EXTENDED означает, что контекст постоянства не будет закрыт, пока вы явно не закроете его. Поскольку ваш Database является одноэлементным компонентом, EntityManager будет жить так же долго, как и ваш компонент (то есть вечно). Вот почему вы видите один и тот же менеджер транзакций во всех потоках, поскольку в вашем расширенном сценарии действительно создан только один.

То, что вам нужно, - это шаблон «открытый менеджер сущностей в представлении», поэтому ваш менеджер сущностей (контекст постоянства) остается открытым на время запроса, а не только для транзакции. Взгляните, например, на OpenEntityManagerInViewFilter.

...