JSF / Spring / JPA / Hibernate应用程序中type = PersistenceContextType.EXTENDED和javax.persistence.OptimisticLockException之间的冲突

时间:2012-03-02 11:06:27

标签: spring hibernate jsf jpa transactions

我正在尝试将纯JSF / Hibernate Web应用程序移植到JSF / Spring 3.0 / Hibernate / JPA应用程序。 我使用依赖注入将EntityManager的实例注入到我的DAO类中。 如果我在@PersistenceContext注释上使用type = PersistenceContextType.EXTENDED属性,     状态在浏览器之间共享,并且不显示登录页面。我试过不同的浏览器,而不仅仅是不同的窗口     就像JSF - session scoped bean shared by browsers on different machines一样 如果我没有指定EXTENDED,我无法在第一次更新后更新我的记录并获得javax.persistence.OptimisticLockException

我最近发现了一个名为View scope的东西,但我不确定这是否是解决方案。请提出一种实现这两个目标的方法 一个。在后续更新时避免使用OptimisticLockException 湾避免跨浏览器共享状态

由于 Sagar R. Kapadia

我的配置和源文件如下

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>

faces-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>

Database.java

@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 个答案:

答案 0 :(得分:1)

EXTENDED表示在您明确关闭持久化上下文之前不会关闭它。由于你的Database是一个单独的bean,所以只要你的bean(永远是),EntityManager就会存在。这就是为什么你在所有线程中看到相同的事务管理器,因为在你的EXTENDED场景中只创建了一个。

您想要的是“视图中的开放实体管理器”模式,因此您的实体管理器(持久性上下文)在请求期间保持打开,而不仅仅是事务。例如,查看OpenEntityManagerInViewFilter