• Hibernate 中对象 set 属性时自动保存入库的问题


    原文地址:https://blog.csdn.net/qqfo24/article/details/83275610

    背景

    在某个项目中,通过 Heibernate 查出某个对象后,对属性进行了 set 操作,并没有进行 update 操作,但是在数据中自动保存了。

    显然这并不是我想要的,我只是想 set 一下属性,在前端显示,并不想入库,但是 Heibernate 自动保存了。

    // 查出对象,原来的 name 为 user1
    User user = userManager.findOne(1);
    // 将userName 设置为 user2 ,用于前端显示,并没有保存
    user.setName("user2");
    // heibernate 自动进行了保存,库中的 name 为 user2

    原因

    Heibernate 中对象分为以下几种状态:

    瞬时状态:

    实际上就是 new 了一个普通的 JavaBean 对象。

    托管状态:

    • 当瞬时对象调用了管理器的 persist() 后,即可将一般的 JavaBean 做为了持久 Bean,该 Bean 的任何属性改动都会牵涉到数据库记录的改动。

    • 一旦该记录 flush 到数据库之后,并且事务提交了,那么此对象不在持久化上下文中,即:变为了游离(没人管的孩子)状态了。在游离状态的时候调用更新、刷新方法后,游离状态对象就变为了在持久化上下文的托管状态了。

    • 通过管理器的 find 方法,将实体从数据库查询出来后,该实体也就变为了托管形态。

    持久化状态:

    当处在托管状态的实体 Bean 被管理器 flush 了,那么就在极短暂的时间进入了持久化状态,事务提交之后,立刻变为了游离状态。您可以把持久化状态当做实实在在的数据库记录。

    游离状态:

    游离状态就是提交到数据库后,事务 commit 后实体的状态,因为事务已经提交了,此时实体的属性任你如何改变,也不会同步到数据库,因为游离是没人管的孩子,不在持久化上下文中。

    销毁对象:

    一般要删除一个持久化对象的时候都是先 find 出来,之后调用 remove 方法删之,此时这个对象就是销毁对象,实际上就是瞬时对象的另一种形态罢了。

    根据上面的各种状态,可以得知。通过 find 查出某个对象后,就进入了托管状态,此时对对象的任何属性改动,都会自动保存到数据库中。

    解决方法

    1. 通过 new 一个新的对象出来进行操作,这个新的对象是瞬时状态,不会自动保存。
    // 查出对象
    User user = userManager.findOne(1);
    // new 一个新的对象
    User newUser = new User();
    // 将需要用到的属性赋予新的对象,对于前端显示
    newUser.setAge(user.getAge());
    newUser.setName("user2");
    // 不要对 newUser 进行保存即可。也不要改变 user 的属性

    在 find 查出的对象 set 属性前,将其状态改为游离状态。这样的话会用到 session 的几个方法:close、clear、evict。

    • close 方法:关闭 session 这样这个对象肯定是游离态了,因为 session 已经关闭了,但是往往我们实际的开发过程中,session 在后面是要用的到的,所以这个方法可行,但是不一定用得上,分清具体的情况。

    • clear 方法:将 session 中的所有的对象全部清除出缓存,这个方式有点劳师动众,不过 session 清除了全部的对象之后自然就会变为游离态了,这样做不是很好吧我感觉。

    • evict 方法:将某一个对象清除出缓存 session,这个方法是很好的实现方式,推荐使用。调用的时候是这样的,session.evict(Object obj) 这样就可以了。

    这边推荐使用 evict 方法,代码如下:

    @PersistenceContext
    private EntityManager entityManager;
    
    ......
    
    // 获取 session
    HibernateEntityManager hEntityManager = (HibernateEntityManager)entityManager;
    Session session = hEntityManager.getSession();
    // 查出对象,原来的 name 为 user1
    User user = userManager.findOne(1);
    // 将对象清除出缓存 session,这样后面对属性的改变就不会自动保存
    session.evict(user);
    // 将userName 设置为 user2 ,用于前端显示
    user.setName("user2");
    // 由于清除出了 session,heibernate 不会对这个对象进行保存,库中的 name 仍为 user1

    总结

    通过 Hibernate 查询出来的对象,改变其属性后,Hibernate 会对其自动保存入库。

    如果不需要使用这个功能,可以通过 new 一个新的对象来进行操作,或者将对象改成游离态。

  • 相关阅读:
    排序之快速排序
    希尔排序
    大数据的乘法
    大数据的乘法实现——C语言
    js函数纪实
    【转】js中$含义及用法
    python基础操作
    git 常用指令
    Django框架学习记录
    【转】Java 字符串拼接 五种方法的性能比较分析 从执行100次到90万次
  • 原文地址:https://www.cnblogs.com/dyh004/p/13879301.html
Copyright © 2020-2023  润新知