我正在将 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;
}
我还使用 Hibernate 4,它与 Spring 兼容。我注释掉了 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 进行注释时,我收到一条错误,提示 No Qualified 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时出错: Autowiring 依赖项注入(inject)失败;嵌套异常是 org.hibernate.service.UnknownUnwrapTypeException:无法解包到请求的类型 [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();
}
好消息是我不再遇到部署问题。日志记录还表明我的更改对服务器产生了一些影响。不幸的是,没有保存任何内容,因此它仍然无法正常工作。
最佳答案
引起我注意的第一件事是在 ManagedBean 上使用 @Transactional 和 @Component。
JSF 和 Spring 肯定是一起工作的,但我从未见过它们在我正在从事的许多项目中以这种方式使用。
我不确定这是否是导致您出现问题的原因,但请考虑更改它。
我会这样做:
a) 定义一些服务层,您可以在其中使用事务包装调用并注入(inject) JPA 类:
@Component
@Transactional
class Service{
@Autowired
private EntityManager em;
@Autowired
private EntityManagerFactory emf;
public String serviceMethod(..){ .. }
}
b) 将其注入(inject) Jsf 的 ManagedBean,同时删除不必要的注释:
@ManagedBean(name="firstTestBean")
public class FirstTestBean {
@ManagedProperty("#{service}")
private Service service;
public String transactionalTest() {
return service.serviceMethod();
}
}
关于java - Spring + Jboss7 @Transactional 不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41752258/