zoukankan      html  css  js  c++  java
  • 解决JPA对查询对象set属性值导致数据更新的问题

    问题描述

    1、开启了数据库事务

    2、通过EntityManager执行查询,获得返回对象

    3、代码业务逻辑处理,其中有对象set属性值的操作

    4、没有执行过JPA的save方法或者update语句

    5、提交数据库事务,发现数据库中对应的数据更新成了新的属性值

    问题复现

    @Transactional
    @Override
    public void selectAndFlush(String id) {
       User user = crudDao.selectByPrimaryKey(id);
       user.setName("testFlushNotUpdateDB");
    }
    Hibernate: selectuser0_.AGE as AGE8_0_, user0_.CARD as CARD9_0_, user0_.NAME as NAME10_0_, user0_.PRICE as PRICE11_0_ from USER user0_ where user0_.ID=?
    
    Hibernate: update USER set AGE=?, CARD=?, NAME=?, PRICE=? where ID=?

    可以看到在set方法之后JPA自动帮我们执行了update操作

    问题原因

    根本原因是因为我们在执行查询以后,查询结果对象在EntityManager上下文中进行了一级缓存,执行set方法以后缓存对象状态【持久态】,事务提交时会自动帮我们flush到数据库中,导致数据被更新,下图为一级缓存对象:

     解决方法

    这里提供4中解决方法:

    1、提交事务之前执行EntityManager.clear()方法,清理缓存对象

    2、业务代码在不需要更新数据时避免直接对查询对象进行set操作,可以使用BeanUtils.copyProperties()方法复制对象,再进行set操作

    3、使用EntityManager.evict()方法清理指定对象

    4、修改JPA的FlushMode,没有测试过,理论可行,代码如下:

    ((Session) getEntityManager().getDelegate()).setFlushMode(FlushMode.MANUAL);
  • 相关阅读:
    HAProxy从零开始到掌握
    学会这15点,让你分分钟拿下Redis数据库
    求一个字符串长度
    js时间戳怎么转成日期格式
    js获取url参数值的两种方式
    js 处理URL实用技巧
    jQuery操作radio、checkbox、select 集合
    js处理url的技巧和归纳
    ajax hash缓存
    jquery ajax跨域
  • 原文地址:https://www.cnblogs.com/changxy-codest/p/15252651.html
Copyright © 2011-2022 走看看