有问题通过CrudRepository保存JPA实体。 它似乎返回传递给它的原始对象,而不将对象持久化到数据库。 我知道这不是正确的方法,但出于测试目的,如果我在保存之前放置一个TransactionSynchronizationManager实例,它似乎仍然正确。 这让我觉得交易经理可能存在问题?
此外,如果我丢弃存储库并使用实体管理器(em),我得到相同的结果,但是如果我调用em.flush(),我会得到异常“Transactionrequiredexception,No Transaction in Progress”。
@Transactional public class UserServiceImpl implements UserService{ @Autowired private UserRepository userRepository; @Autowired private EntityManagerFactory emf; @Override @Transactional(readOnly=false) public User save(User user) { // EntityManager em = emf.createEntityManager(); //Object persists when adding following line // TransactionSynchronizationManager.bindResource(emf , new EntityManagerHolder(em)); return userRepository.save(user); } } @ComponentScan(basePackages = {"..."}) @Import(value={DataContextConfig.class,SecurityConfig.class}) public class AppConfig{ } @Configuration @ComponentScan(basePackages = {".."}) @Import(DataConfig.class) public class DataContextConfig { } @Configuration @EnableTransactionManagement(mode=AdviceMode.ASPECTJ) @EnableJpaRepositories(value={"com.repository"}, entityManagerFactoryRef="entityManagerFactory", transactionManagerRef="transactionManager") @PropertySource("classpath:data.properties") public class DataConfig { ... @Bean public PlatformTransactionManager transactionManager() { JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory((EntityManagerFactory) entityManagerFactory()); return txManager; } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); factory.setPackagesToScan("..."); factory.setJpaPropertyMap(jpaProperties()); factory.setDataSource(dbSource()); return factory; } @Bean public DriverManagerDataSource dbSource(){ DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource(); driverManagerDataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName")); driverManagerDataSource.setUrl(environment.getRequiredProperty("jdbc.url")); driverManagerDataSource.setUsername(environment.getRequiredProperty("jdbc.username")); driverManagerDataSource.setPassword(environment.getRequiredProperty("jdbc.password")); return driverManagerDataSource; } }我上传了一个隔离异常的小项目。 压缩并运行AccountTester.class http://www14.zippyshare.com/v/81636273/file.html
Having issues saving JPA Entity through CrudRepository. It seems to return the original object that was passed to it without persisting the object to the database. I know this is not the correct way to do it but for testing purposes if I place an instance of TransactionSynchronizationManager before the save, it seems persist correctly. This leads me to think maybe there an issue the Transaction Manager?
In addition if I discard the repository and use the Entity Manager (em) I get the same result, however if I call em.flush(), I get the Exception "Transactionrequiredexception, No Transaction in Progress".
@Transactional public class UserServiceImpl implements UserService{ @Autowired private UserRepository userRepository; @Autowired private EntityManagerFactory emf; @Override @Transactional(readOnly=false) public User save(User user) { // EntityManager em = emf.createEntityManager(); //Object persists when adding following line // TransactionSynchronizationManager.bindResource(emf , new EntityManagerHolder(em)); return userRepository.save(user); } } @ComponentScan(basePackages = {"..."}) @Import(value={DataContextConfig.class,SecurityConfig.class}) public class AppConfig{ } @Configuration @ComponentScan(basePackages = {".."}) @Import(DataConfig.class) public class DataContextConfig { } @Configuration @EnableTransactionManagement(mode=AdviceMode.ASPECTJ) @EnableJpaRepositories(value={"com.repository"}, entityManagerFactoryRef="entityManagerFactory", transactionManagerRef="transactionManager") @PropertySource("classpath:data.properties") public class DataConfig { ... @Bean public PlatformTransactionManager transactionManager() { JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory((EntityManagerFactory) entityManagerFactory()); return txManager; } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); factory.setPackagesToScan("..."); factory.setJpaPropertyMap(jpaProperties()); factory.setDataSource(dbSource()); return factory; } @Bean public DriverManagerDataSource dbSource(){ DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource(); driverManagerDataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName")); driverManagerDataSource.setUrl(environment.getRequiredProperty("jdbc.url")); driverManagerDataSource.setUsername(environment.getRequiredProperty("jdbc.username")); driverManagerDataSource.setPassword(environment.getRequiredProperty("jdbc.password")); return driverManagerDataSource; } }I have uploaded a small project that isolates the exception. Zip and run AccountTester.class http://www14.zippyshare.com/v/81636273/file.html
最满意答案
根据您的示例项目。 以下是为避免TransactionRequiredException: no transaction is in progress修改的唯一类TransactionRequiredException: no transaction is in progress并且成功插入帐户:
package com.jpa.base.repository; import com.jpa.base.entity.Account; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; @Repository public interface AccountRepository extends CrudRepository<Account, Long> { public Account findByEmailAddress(@Param(value = "emailAddress") String emailAddress); public Account findByAccountId(@Param(value = "accountId") Long accountId); }原件供参考
您需要使用@Repository (不是您的服务)标记Spring Data JPA存储库。 看这里
package com.jpa.base.service.impl; import com.jpa.base.entity.Account; import com.jpa.base.repository.AccountRepository; import com.jpa.base.service.AccountService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service("accountService") public class AccountServiceImpl implements AccountService { @Autowired private AccountRepository accountRepository; @Override @Transactional(readOnly = true) public Account findByAccountId(Long accountId) { return accountRepository.findByAccountId(accountId); } @Override @Transactional(readOnly = true) public Account findByEmailAddress(String emailAddress) { return accountRepository.findByEmailAddress(emailAddress); } @Override @Transactional public Account save(Account account) { return accountRepository.save(account); } }原件供参考
请注意从服务中删除@Repository (需要在Spring Data JPA存储库界面上)并使用accountRepository在save(...)方法中保留实体的accountRepository 。
不确定为什么你试图使用EntityManagerFactory来创建一个新的EntityManager (如果你真的需要一个EntityManager实例,你应该只注入配置的EntityManager ,而不是工厂)。 这也恰好是您的TransactionRequiredException的原因。
Anyhoo,当你可以使用你的存储库来保存你的实体时,为什么还要烦恼呢。 现在运行AccountTester可以生成所需的功能:
... Hibernate: insert into account (email_address, name, version) values (?, ?, ?) INFO : com.jpa.base.entity.AccountTester - Account Saved: Account Id: 3, Email Address:james.brown@outlook.com, Name: James Brown, Version: 0It turns out there were multiple @EnableTransactionManagement(mode=AdviceMode.ASPECTJ) annotations within the application. This was cause of the problem, after removing the one within the Neo4j @Configuration Class the problem went away.
更多推荐
发布评论