【问题标题】:Spring + Jboss7 @Transactional Not workingSpring + Jboss7 @Transactional 不工作
【发布时间】:2017-06-04 18:28:44
【问题描述】:

我正在将我的 JBoss 服务器从 5 升级到 7,现在正在合并 Spring 4。我在使用 Spring 的 @Transactional 注释时遇到了一些问题。它似乎没有工作。我也在尝试使用基于 java 的配置文件而不是 xml 文件(我相信我可以在不使用任何 xml 的情况下逃脱,但如果我错了,请纠正我)。问题是我的数据库中没有保存任何内容,这让我相信@Transactional 不起作用。这是我的配置文件:

@Configuration
@ComponentScan
@EnableTransactionManagement
public class SpringBeanConfiguration {

@Bean
public FirstTestBean firstTestBean() {
    return new FirstTestBean();
}

@Bean
public TestService testService() {
    return new TestServiceImpl();
}

@Bean 
public SomethingDAO somethingDAO(){
    return new SomethingDAOImpl();
}

@Bean 
public GeneralDAO generalDAO(){
    return new GeneralDAOImpl();
}

这是一个带有@Transactional 方法的测试类:

//@RequestScoped
@ManagedBean(name="firstTestBean")
@Component
public class FirstTestBean {

private EntityManager em;
private EntityManagerFactory emf;


@Transactional
public String transactionalTest() {
    //ApplicationContext context = new AnnotationConfigApplicationContext(SpringBeanConfiguration.class);
    Something something = new Something();
    getEntityManager().persist(something);
    return "dkljs";
}


public EntityManager getEntityManager() {
    if (em == null) {
        emf = Persistence.createEntityManagerFactory("xxx");
        em = emf.createEntityManager();
    }
    return em;
}

我也在使用与 Spring 兼容的 Hibernate 4。我注释掉了ApplicationContext,因为我在 JBoss 启动时单独运行了它。我之前使用它来访问一个 bean,但我已经简化了一些事情以使 @Transactional 工作,因此在这里不需要它。 @ComponentScan 不需要参数,因为这些类在同一个包中。

任何帮助将不胜感激。谢谢!

更新

我已经做了一些建议的更改。事情似乎正朝着正确的方向发展。

这是我更新的文件:

@ManagedBean(name="firstTestBean")
public class FirstTestBean {

public String getTestString() {     
    ApplicationContext context = new AnnotationConfigApplicationContext(SpringBeanConfiguration.class);
    TestService testService = context.getBean(TestService.class);       


    testService.transactionalTest();
    return "adfs";
}

public String test() {
    return "firstTestBean works";
}   
}

注意 - 其中一些类将作为独立应用程序在 Jboss 应用程序服务器之外运行,因此,我在 FirstTestBean 中实例化 TestService 时远离 FacesContext,因为 Spring bean 独立工作,但 FacesContext bean不要。

@Component
@Transactional
public class TestServiceImpl implements TestService {

public GeneralDAO generalDAO;

//@Autowired
private EntityManager em;

//@Autowired
private EntityManagerFactory emf;


public TestServiceImpl(){}



public String transactionTest() {
    Something something = new Something();
    getEntityManager().persist(something);
    return "dkljs";
}

EntityManager 和 EntityManagerFactory 上的@autowired 不起作用 - 当它像建议的那样使用 @autowired 进行注释时,我收到一条错误消息,指出没有 EntityManager 类型的合格 Bean。

@Configuration
@ComponentScan
@EnableTransactionManagement
public class SpringBeanConfiguration implements     TransactionManagementConfigurer {



@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
    String hibernatePropsFilePath = "/[path]/hibernate.cfg.xml";
    File hibernatePropsFile = new File(hibernatePropsFilePath);

    org.hibernate.cfg.Configuration cfg = new org.hibernate.cfg.Configuration().configure(hibernatePropsFile);
    SessionFactory sessionFactory = cfg.buildSessionFactory();

    HibernateTransactionManager txManager = new HibernateTransactionManager(sessionFactory);
    txManager.setNestedTransactionAllowed(true);
    return txManager;
}

}

我现在得到的错误是:引起:org.springframework.beans.factory.BeanCreationException:创建名为“org.springframework.context.event.internalEventListenerProcessor”的bean时出错:bean初始化失败 ;嵌套异常是 org.springframework.beans.factory.BeanCreationException:创建名为 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' 的 bean 时出错: 注入自动装配的依赖项失败;嵌套异常是 org.hibernate.service.UnknownUnwrapTypeException: Cannot unwrap to requested type [javax.sql.DataSource]

我认为这意味着@Transactional 至少已被识别,但我在使其正常工作时遇到了一些问题。任何进一步的建议将不胜感激。

更多更新

找到这篇文章:http://www.baeldung.com/the-persistence-layer-with-spring-and-jpa#javaconfig

并跟随它。我的新配置文件:

@Configuration
@ComponentScan
@EnableTransactionManagement
public class SpringBeanConfiguration { //implements  TransactionManagementConfigurer {

   @Bean
   public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
      LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
      em.setDataSource(dataSource());
      em.setPackagesToScan(new String[] { "xxx.xxx.xxx" });

      JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
      em.setJpaVendorAdapter(vendorAdapter);
   //   em.setJpaProperties(additionalProperties());

      return em;
   }

   @Bean
   public DataSource dataSource(){
      DriverManagerDataSource dataSource = new DriverManagerDataSource();
      dataSource.setDriverClassName("com.mysql.jdbc.Driver");
      dataSource.setUrl("jdbc:mysql://localhost:3306/jboss_test");
      dataSource.setUsername( "root" );
      dataSource.setPassword( "root" );
      return dataSource;
   }

   @Bean
   public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
      JpaTransactionManager transactionManager = new JpaTransactionManager();
      transactionManager.setEntityManagerFactory(emf);

      return transactionManager;
   }

   @Bean
   public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
      return new PersistenceExceptionTranslationPostProcessor();
   }

好消息是我不再遇到部署问题。日志记录还表明我的更改对服务器产生了一些影响。不幸的是,没有任何东西被保存,所以它仍然不能正常工作。

【问题讨论】:

    标签: java spring hibernate jsf jboss


    【解决方案1】:

    首先引起我注意的是 @Transactional 和 @Component 在 ManagedBean 上的使用。

    JSF 和 Spring 绝对可以一起工作,但我从未在我从事的许多项目中看到它们以这种方式使用过。

    我不确定这是否是您的问题的原因,但请考虑改变它。

    我会这样做:

    a) 定义一些服务层,您可以在其中使用事务包装调用并注入 JPA 类:

    @Component
    @Transactional
    class Service{
    
       @Autowired
       private EntityManager em;
    
       @Autowired
       private EntityManagerFactory emf;
    
       public String serviceMethod(..){ .. }
    
    }
    

    b) 将其注入到 Jsf 的 ManagedBean 中,同时删除不必要的注释:

    @ManagedBean(name="firstTestBean")
    public class FirstTestBean {
    
      @ManagedProperty("#{service}")
      private Service service;
    
      public String transactionalTest() {
          return service.serviceMethod(); 
      }
    
    }
    

    【讨论】:

    • 我最初有这个,但尝试简化它只是为了看看我是否可以得到任何工作......我会将更改恢复到我最初的更改并尝试你所说的。我会发布更新。感谢您的帮助。
    • 做了一些更新。抱歉回复晚了 - 想先修补一下。
    • 据我记得,绑定 JPA、Hibernate 和 Spring 的方式有些不同(至少我使用了不同的配置)。尝试注入 SessionFactory 而不是 EntityManagerFactory 并查看它是否有效。如果你真的需要坚持使用 JPA,那么我会给你一些配置链接
    • 我尝试自动装配 Sessionfactory 并得到与 EntityManagerFactory 相同的错误。坚持使用 JPA 绝对是理想的选择。配置链接肯定会受到赞赏。谢谢!
    • 找到一篇有帮助的文章 - 我在上面列出了一些更改,但仍然不是我需要的地方
    【解决方案2】:

    好的,所以我终于明白了(请查看我的 OP 以了解所有导致我达到这一点的更新)。

    这是我的最终配置文件:

    @Configuration
    @ComponentScan
    @EnableTransactionManagement
    public class SpringBeanConfiguration { 
    
       @Bean
       public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
          LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
          em.setPersistenceUnitName("myPersistenceContext");
          em.setDataSource(dataSource());
          em.setPackagesToScan(new String[] { "xxx.xxx.xxx" });
    
          JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
          em.setJpaVendorAdapter(vendorAdapter);
       //   em.setJpaProperties(additionalProperties());
    
          return em;
       }
    
       @Bean
       public DataSource dataSource(){
          DriverManagerDataSource dataSource = new DriverManagerDataSource();
          dataSource.setDriverClassName("com.mysql.jdbc.Driver");
          dataSource.setUrl("jdbc:mysql://localhost:3306/jboss_test");
          dataSource.setUsername( "root" );
          dataSource.setPassword( "root" );
          return dataSource;
       }
    
       @Bean
       public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
          JtaTransactionManager transactionManager = new JtaTransactionManager();
         // transactionManager.setEntityManagerFactory(emf);
    
          return transactionManager;
       }
    
       @Bean
       public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
          return new PersistenceExceptionTranslationPostProcessor();
       }
    

    所以首先,我添加了

    em.setPersistenceUnitName("myPersistenceContext");  
    

    这给了我错误:

    Spring IllegalStateException: A JTA EntityManager 不能使用 getTransaction()

    从这里开始,我做了一些研究 (Spring IllegalStateException: A JTA EntityManager cannot use getTransaction())

    改变了

    JpaTransactionManager transactionManager = new JpaTransactionManager();
    

    JtaTransactionManager transactionManager = new JtaTransactionManager();
    

    另外,我的 persistence.xml 文件是:

        <persistence-unit name="myPersistenceContext">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:jboss/datasources/myDS</jta-data-source>
        <class>xxx.xxx.xxx.Something</class>    
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
    
        <properties>
            <property name="hibernate.cache.use_second_level_cache" value="true" />
            <property name="hibernate.id.new_generator_mappings" value="false"/>
            <property name="hibernate.classloading.use_current_tccl_as_parent" value="false"/>
            <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" /> 
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.archive.autodetection" value="class, hbm" />
        </properties>
    </persistence-unit>
    

    感谢 Maciej Kowalski 的帮助 - 你把我推向了正确的方向。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-19
      • 2016-10-04
      • 2012-01-30
      • 2012-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多