[英]Spring 4, JBoss 7, @Configuration Bean equivalent XML - Spring Transactions
It seem like EntityManager is NOT flushing out the changes to the database. 似乎EntityManager并没有清除对数据库的更改。 What makes this problem harder is that there is no exception thrown.
使这个问题更难的是没有引发异常。 I am using declarative transactions to define my transaction boundaries with the following flow:
我正在使用声明式事务通过以下流程定义我的事务边界:
SignUpController --> @Transactional: Tx.Start --> AccountServiceImpl.createAccount --> AccountDAOImpl.createAccount --> Tx.Commit --> SignUpController SignUpController-> @Transactional:Tx.Start-> AccountServiceImpl.createAccount-> AccountDAOImpl.createAccount-> Tx.Commit-> SignUpController
From my investigation it seems like: 从我的调查看来:
1.Spring is properly defining the Transaction Boundaries using @Transactional. 1.Spring使用@Transactional正确定义了交易边界。 Hence Transaction are being created
因此正在创建交易
2.Also please Note the I am using the SharedEntityManagerBean, which means I CANNOT explicitly define my transaction boundaries eg: 2.也请注意,我正在使用SharedEntityManagerBean,这意味着我无法显式定义我的交易边界,例如:
em.getTransaction().begin();
em.persist(entity);
em.getTransaction().commit();
The above code results in the following exception: Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead 上面的代码导致以下异常:不允许在共享EntityManager上创建事务-改用Spring事务或EJB CMT
Below is the relevant code and configuration. 以下是相关的代码和配置。 Any assistance will be greatly appreciated.
任何帮助将不胜感激。 Thanks.
谢谢。
MainConfig.java: MainConfig.java:
@Configuration
@ComponentScan(basePackages="com",excludeFilters= {@Filter(Configuration.class)})
@EnableTransactionManagement
public class MainConfig {
@Bean
public DataSource dataSource() {
DataSource ds = (DataSource)getFromInitialContext("java:jboss/datasources/PrimaryDB");
return ds;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
@Bean
public EntityManagerFactory entityManagerFactory() {
EntityManagerFactory emf = (EntityManagerFactory) getFromInitialContext("java:jboss/entityManagerFactory");
return emf;
}
private Object getFromInitialContext(String jndiValue) {
Context ctx = null;
Object object = null;
try {
ctx = new InitialContext();
object = ctx.lookup(jndiValue);
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return object;
}
}
persistance.xml: persistance.xml:
<persistence-unit name="PrimaryDB" transaction-type="JTA">
<jta-data-source>java:jboss/datasources/PrimaryDB</jta-data-source>
<class>com.domain.entities.Account</class>
<properties>
<!-- Bind entity manager factory to JNDI at java:jboss/myEntityManagerFactory -->
<property name="jboss.entity.manager.factory.jndi.name"
value="java:jboss/entityManagerFactory" />
<!-- Properties for Hibernate -->
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.use_sql_comments" value="true" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
</properties>
</persistence-unit>
AccountServiceImpl: AccountServiceImpl:
@Service
public class AccountServiceImpl implements AccountService {
@Inject
AccountDAO accountDAOImpl;
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public Account createAccount(SignupForm form, BindingResult formBinding) {
TransactionDebugUtil.transactionRequired("AccountServiceImpl.createAccount");
Account account =
new Account(form.getUsername(), form.getPassword(),form.getFirstName(), form.getLastName());
try {
accountDAOImpl.createAccount(account);
} catch (Exception ex) {
formBinding.rejectValue("username", "user.duplicateUsername",
"already in use: " + ex.getMessage());
return null;
}
return account;
}
}
AccountDAOImpl.java: AccountDAOImpl.java:
@Repository
public class AccountDAOImpl extends GenericJpaDAO<Account> implements AccountDAO {
@Override
@PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
entityManager.setFlushMode(FlushModeType.COMMIT);
}
@Override
public void createAccount(Account account) throws UsernameAlreadyInUseException {
entityManager.persist(account);
}
Hi the confusion was caused due to using annotations for configuring the transaction manager rather then XML. 嗨,这是由于使用注释配置事务管理器而不是XML引起的。
Typical XML Configuration for SpringTransaction: SpringTransaction的典型XML配置:
1. 1。
<tx:annotation-driven />
^It scans all beans in the application context and creates AOP interceptor for those which are annotated.This is done via the SpringTransactionAnnotationParser, which is used by TransactionInterceptor. ^它扫描应用程序上下文中的所有bean并为被注释的bean创建AOP拦截器,这是通过TransactionInterceptor使用的SpringTransactionAnnotationParser完成的。
@EnableTransactionManagement
^This is the equivalent configuration bean annotation to allow transactional support ^这是等效的配置bean批注,以允许事务支持
2 . 2。 JTA datasource is defined in the persistence.xml.
JTA数据源在persistence.xml中定义。 JBoss 7 automatically creates a JTA Transaction Manager and binds it to the following JNDI Location: java:/TransactionManager by default.
JBoss 7自动创建一个JTA事务管理器并将其绑定到以下JNDI位置:默认情况下为java:/ TransactionManager。 This Transaction Manager is automatically discovered in spring with the following xml configuration:
该事务管理器是在春季使用以下xml配置自动发现的:
<tx:jta-transaction-manager />
The equivalent annotation configuration for this is: 与此等效的注释配置为:
@Bean
public PlatformTransactionManager transactionManager() {
JtaTransactionManager txManager = new JtaTransactionManager();
return txManager;
}
This resolved my issue. 这解决了我的问题。 Thanks @geoand for your help.
感谢@geoand的帮助。
this kind of behaviour usually happens when we dont have @transactional on the persistent method. 当我们在持久化方法上没有@transactional时,通常会发生这种行为。
so add @Transactional
on top of method like below 所以在下面的方法顶部添加
@Transactional
@Override
@Transactional
public void createAccount(Account account) throws UsernameAlreadyInUseException {
entityManager.persist(account);
}
You are not handling transaction management correctly. 您没有正确处理事务管理。 Replace your transaction manager bean with:
将您的事务管理器bean替换为:
@Bean
public PlatformTransactionManager transactionManager() {
final JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory());
return txManager;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.