使用CrudRepository保留JPA实体(Persisting JPA Entity using CrudRepository)

编程入门 行业动态 更新时间:2024-10-25 04:18:39
使用CrudRepository保留JPA实体(Persisting JPA Entity using CrudRepository)

有问题通过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: 0

It 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.

更多推荐

本文发布于:2023-07-16 10:00:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1126868.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:实体   JPA   CrudRepository   Persisting   Entity

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!