通过CrudRepository保存JPA实体时遇到问题。它似乎返回传递给它的原始对象,而不将对象持久化到数据库。我知道这不是正确的方法,但出于测试目的,如果我在保存之前放置一个TransactionSynchronizationManager实例,它似乎仍然正确。这让我觉得交易管理器可能存在问题吗?
此外,如果我丢弃存储库并使用实体管理器(em),我会得到相同的结果,但是如果我调用em.flush(),我会得到异常" Transactionrequiredexception,No Transaction in Progress&#34 ;。
@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
答案 0 :(得分:1)
根据您的示例项目。
以下是为避免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存储库。 See here
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(...)
方法中保留实体。< / p>
不确定为什么要尝试使用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: 0
答案 1 :(得分:0)
事实证明,应用程序中有多个@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)注释。这是导致问题的原因,在删除Neo4j @Configuration Class中的问题后,问题就消失了。