我正在将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上的@autowired和EntityManagerFactory都不起作用 - 我收到了一个错误,说明没有合格的Bean类型为EntityManager,当它被@autowired注释为建议时。
@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:无法解包到请求的类型[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();
}
好消息是我不再遇到部署问题。日志记录还表明我的更改对服务器有一些影响。不幸的是,没有任何东西被保存,所以它仍然不能正常工作。
答案 0 :(得分:2)
引起我注意的第一件事是在ManagedBean上使用@Transactional和@Component。
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();
}
}
答案 1 :(得分:0)
好的,所以我终于明白了(查看我的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: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的帮助 - 你把我推向正确的方向。