Spring + Jboss7 @Transactional 不工作
Posted
技术标签:
【中文标题】Spring + Jboss7 @Transactional 不工作【英文标题】:Spring + Jboss7 @Transactional Not working 【发布时间】: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();
好消息是我不再遇到部署问题。日志记录还表明我的更改对服务器产生了一些影响。不幸的是,没有任何东西被保存,所以它仍然不能正常工作。
【问题讨论】:
【参考方案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 的帮助 - 你把我推向了正确的方向。
【讨论】:
以上是关于Spring + Jboss7 @Transactional 不工作的主要内容,如果未能解决你的问题,请参考以下文章
Jboss 7 - Spring - 使用 Jboss TransactionManager
为啥从 JBoss 7.1.0EAP 到 Oracle 11g 生成了 100 个幽灵 Oracle 会话
报错解决:No Hibernate Session bound to thread, and configuration does not allow creation of non-transact