当前位置: 首页 > 工具软件 > Dialect App > 使用案例 >

Spring3 + JPA2 + Java EE6 App Server =配置混乱

葛越
2023-12-01
Spring很棒,JavaEE6很棒,最新的JavaEE6 Application服务器也很棒。 这篇文章不是Spring Vs JavaEE6上的专栏文章,而是我在JBoss AS-7.1 App Server上移植Spring3 + JPA2(Hibernate)应用程序的经验。

我的应用程序要求非常简单:使用Spring3.1和JPA2(休眠)开发几个基于SOAP的Web服务,并将其托管在JBoss AS 7.1上。

因此,我开始创建一个多模块maven项目,其中一个jar模块包含使用Spring&JPA的服务实现,另一个war模块将该服务公开为基于SOAP的Web服务。 但是关键部分是服务需要针对某些服务方法与多个数据库进行对话。

我知道从Spring获得的JPA2集成支持,但没有persistence.xml和很酷的packagesToScan属性,这使工作变得更轻松。 我配置了2个数据源,2个LocalContainerEntityManagerFactoryBeans,注册了2个JpaTransactionManagers并启用了基于注释的事务管理支持。

<tx:annotation-driven transaction-manager='txnManager1'/>
 <tx:annotation-driven transaction-manager='txnManager2'/>
 
 <bean class='org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor'/>
 <bean class='org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor'/><!-- This will throw error because it found multiple EntityManagerFactory beans -->
 
 <bean id='txnManager1' 
   class='org.springframework.orm.jpa.JpaTransactionManager'
         p:entityManagerFactory-ref='emf1'/>
    
    <bean id='txnManager2' 
   class='org.springframework.orm.jpa.JpaTransactionManager'
         p:entityManagerFactory-ref='emf2'/>         
       
    <bean id='emf1' class='org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean'>
        <property name='persistenceUnitName' value='Sivalabs1PU'></property>        
        <property name='dataSource' ref='dataSource1'></property>
        <property name='jpaVendorAdapter'>
         <bean id='jpaAdapter' class='org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter'
            p:showSql='${hibernate.show_sql}'/>
        </property>
        <property name='jpaProperties'>
         <props>
          <prop key='hibernate.dialect'>${hibernate.dialect}</prop>
          <prop key='hibernate.hbm2ddl.auto'>${hibernate.hbm2ddl.auto}</prop>
         </props>
        </property>
        <property name='packagesToScan' value='com.sivalabs.springdemo.entities'></property>
        <property name='loadTimeWeaver'>
          <bean class='org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver'/>
        </property>
        
    </bean> 
    
    <bean id='emf2' class='org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean'>
        <property name='persistenceUnitName' value='Sivalabs2PU'></property>
        <property name='dataSource' ref='dataSource2'></property>
        <property name='jpaVendorAdapter'>
         <bean id='jpaAdapter' class='org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter'
            p:showSql='${hibernate.show_sql}'/>
        </property>
        <property name='jpaProperties'>
         <props>
          <prop key='hibernate.dialect'>${hibernate.dialect}</prop>
          <prop key='hibernate.hbm2ddl.auto'>${hibernate.hbm2ddl.auto}</prop>
         </props>
        </property>
        <property name='packagesToScan' value='com.sivalabs.springdemo.entities'></property>
        <property name='loadTimeWeaver'>
          <bean class='org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver'/>
        </property>
        
    </bean> 
 
 <bean id='dataSource1' class='org.apache.commons.dbcp.BasicDataSource'>
  <property name='driverClassName' value='${node1.jdbc.driverClassName}'></property>
  <property name='url' value='${node1.jdbc.url}'></property>
  <property name='username' value='${node1.jdbc.username}'></property>
  <property name='password' value='${node1.jdbc.password}'></property>
 </bean>
 
 <bean id='dataSource2' class='org.apache.commons.dbcp.BasicDataSource'>
  <property name='driverClassName' value='${node2.jdbc.driverClassName}'></property>
  <property name='url' value='${node2.jdbc.url}'></property>
  <property name='username' value='${node2.jdbc.username}'></property>
  <property name='password' value='${node2.jdbc.password}'></property>
 </bean>

此后,我意识到将Entitymanager与正确的PersistenceUnit绑定,我需要将persistenceUnitName赋予LocalContainerEntityManagerFactoryBean。

<bean class='org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor'>
  <property name='persistenceUnits' >
      <map>
        <entry key='unit1' value='Sivalabs1PU'/>
        <entry key='unit2' value='Sivalabs2PU'/>
      </map>
  </property>
 </bean>
 
 <bean id='emf1' class='org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean'>
        <property name='persistenceUnitName' value='Sivalabs1PU'></property>
        <property name='dataSource' ref='dataSource1'></property>
        ....
  ....        
    </bean> 
    
    <bean id='emf2' class='org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean'>
        <property name='persistenceUnitName' value='Sivalabs2PU'></property>
        <property name='dataSource' ref='dataSource2'></property>
        ....
  ....        
    </bean>

然后在我的Service Bean中,将EntityManager和事务管理器粘合在一起,如下所示:

@Service
public class AdminUserService implements UserService
{
 @PersistenceContext(unitName='Sivalabs1PU')
 private EntityManager sivalabs1EM;
 @PersistenceContext(unitName='Sivalabs2PU')
 private EntityManager sivalabs2EM;
 
 @Override
 @Transactional('txnManager1')
 public List<User> getAllUsersFromSivalabs1DB() {
  return sivalabs1EM.createQuery('from User', User.class).getResultList();
 }

 @Override
 @Transactional('txnManager2')
 public List<User> getAllUsersFromSivalabs2DB() {
  return sivalabs2EM.createQuery('from User', User.class).getResultList();
 }
 
}

现在,通过此设置,我得到了异常提示“找不到名称为'Sivalabs1PU'的持久性单元”。 然后,在进行一些谷歌搜索之后,我创建了META-INF / persistence.xml文件,如下所示:

<persistence>

   <persistence-unit name='Sivalabs1PU' transaction-type='RESOURCE_LOCAL'>     
   </persistence-unit>
   
   <persistence-unit name='Sivalabs2PU'  transaction-type='RESOURCE_LOCAL'>     
   </persistence-unit>
   
</persistence>

现在,持久性单元名称错误得到解决,并出现其他异常,说明“未从[用户]映射用户”。 User类使用@Entity注释,并且位于“ com.sivalabs.springdemo.entities ”包中,我将其配置为“ packagesToScan ”属性。 我不明白为什么'packagesToScan'属性不起作用,如果没有persistence.xml,它会很好地工作。 所以暂时我在persistence.xml文件中配置了实体类。

<persistence>

   <persistence-unit name='Sivalabs1PU' transaction-type='RESOURCE_LOCAL'>    
  <class>com.sivalabs.springdemo.entities.User</class>   
   </persistence-unit>
   
   <persistence-unit name='Sivalabs2PU'  transaction-type='RESOURCE_LOCAL'>    
  <class>com.sivalabs.springdemo.entities.User</class>
   </persistence-unit>
   
</persistence>

最终,当我运行调用AdminUserService方法的JUnit测试时,一切看起来都很好并且工作正常。 然后,我在JBoss AS 7.1服务器上部署了war文件,然后再次出现了很多错误。 JBoss抱怨“当未设置“ hibernate.dialect”时,Connection不能为空”。 '[PersistenceUnit:Sivalabs1PU]无法建立EntityManagerFactory。

经过几分钟的思考,我了解到JBoss服务器正在尝试执行“配置约定”规则应做的事情。 JBoss试图创建EntityManagerFactory,因为它在类路径中找到了META-INF / persistence.xml。 但是由于它不包含jdbc连接细节,因此引发了Error。

再次谷歌搜索之后,我发现我们可以将persistence.xml重命名为其他名称(spring-persistence.xml),并使用Spring将此新名称连接起来,如下所示:

<bean id='emf1' class='org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean'>
        <property name='persistenceUnitName' value='Sivalabs1PU'></property>
  <property name='persistenceXmlLocation' value='classpath:META-INF/spring-persistence.xml'/>
        <property name='dataSource' ref='dataSource1'></property>
        ....
  ....        
    </bean> 
    
    <bean id='emf2' class='org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean'>
        <property name='persistenceUnitName' value='Sivalabs2PU'></property>
  <property name='persistenceXmlLocation' value='classpath:META-INF/spring-persistence.xml'/>
        <property name='dataSource' ref='dataSource2'></property>
        ....
  ....        
    </bean>

最终,我成功地使该应用程序在JBoss AS 7.1上运行(仍然不知道还有多少其他漏洞)。

但是在这里我不了解Spring的一些概念:
1.当我尝试提供persistenceUnitName时,为什么Spring正在检查该名称是否存在于persistence.xml中? 无论如何,persistence.xml不含任何单元名称!
2.为什么在与persistence.xml一起使用时packagesToScan机制失败? 是弹簧虫吗?

一切似乎都正常,只是缺少一件事,在我与Spring和Tomcat一起工作时通常会露出微笑:-(

我非常喜欢Spring框架,自2006年以来一直在使用它,在编写Spring代码的同时我非常喜欢。 这并不意味着我不喜欢CDI,EJB3,JAX-RS :-)

无论如何,通过以上所有练习,我感觉就像Spring3 + JPA2 + JavaEE6AppServer = Confusion Over Configuration ,这只是我(一个普通的Java开发人员)的意见。

再说一次:Spring很棒,JavaEE6很棒,最新的JavaEE6 Application服务器也很棒:-)。

参考: Spring3 + JPA2 + JavaEE6AppServer =来自我们的JCG合作伙伴 Siva Reddy的“配置混乱”,来自My Experiments on Technology博客。


翻译自: https://www.javacodegeeks.com/2012/10/spring3-jpa2-java-ee6-app-server.html

 类似资料: