配置Eclipse JPA Dialect后如何使用,解决实体未主动保存自动入库问题
问题解决:EclipseLink托管实体修改自动同步数据库问题
根因说明
你遇到的未主动调用save方法就自动入库的问题,本质是Spring托管的业务方法默认运行在事务上下文内,查询返回的实体处于托管状态,EclipseLink会在事务提交时自动将所有托管实体的变更刷入数据库,无需显式调用持久化方法。
实现实体脱管的操作方案
你可以通过手动控制事务生命周期,让实体在修改前进入脱管状态,修改操作就不会同步到数据库,具体实现如下:
步骤1:补充依赖注入
在FruitService中注入EntityManager用于手动控制实体状态和事务:
@Service public class FruitService { @Autowired private FruitRepository fruitRepository; // 注入JPA实体管理器 @PersistenceContext private EntityManager entityManager;
步骤2:两种实现脱管的代码方案
方案A:手动开启独立事务,事务结束后实体自动脱管
利用beginTransaction()开启独立事务,事务提交后关联的实体自动变为脱管状态:
@Override public Fruit getFruitById(long fruitId) { Fruit testFruitObj = null; // 开启独立的实体管理器上下文 EntityManager em = entityManager.getEntityManagerFactory().createEntityManager(); EntityTransaction transaction = em.getTransaction(); try { // 开启事务 transaction.begin(); testFruitObj = em.find(Fruit.class, fruitId); // 提交事务,当前上下文关闭 transaction.commit(); } catch (Exception e) { if (transaction.isActive()) { transaction.rollback(); } throw e; } finally { em.close(); } // 此时testFruitObj已脱管,修改不会同步到数据库 testFruitObj.setFruitName("This is an apple"); // 二次查询验证数据未变更 Fruit fruitObj = fruitRepository.findById(fruitId).get(); return fruitObj; }
方案B:查询后手动脱管实体(更简洁)
如果不需要调整事务逻辑,直接对查询到的托管实体调用detach方法即可手动脱管:
@Override public Fruit getFruitById(long fruitId) { Fruit testFruitObj = fruitRepository.findById(fruitId).get(); // 手动将实体从持久化上下文中移除,变为脱管状态 entityManager.detach(testFruitObj); testFruitObj.setFruitName("This is an apple"); // 修改不会同步到数据库 Fruit fruitObj = fruitRepository.findById(fruitId).get(); return fruitObj; }
注意:你当前已配置的
EclipseLinkJpaDialect已经适配Spring事务管理体系,上述两种方案都可以直接运行,无需修改现有配置。
内容的提问来源于stack exchange,提问作者Trainer
相关产品推荐
相关产品推荐

