【问题标题】:Hibernate - lazy load and update single object from the dbHibernate - 延迟加载和更新数据库中的单个对象
【发布时间】:2020-06-21 19:21:11
【问题描述】:

我最近致力于优化我的应用程序性能,我注意到当我延迟加载具有 MazyToOne 关系的依赖项时,hibernate 提供的对象不仅延迟加载对象本身,而且还延迟加载它的所有字段 - 所以,它让我想如果我可以利用它来发挥我的优势 让我们想象一下这样的情况

@Transactional
public void updateUserNameToHarry(Long userId){
  User u = dao.findById(userId);
  u.setName("Harry");
}

所以我们打开了一个事务,将 Harry 加载到我们的持久化上下文中,并更新了他的名字。 一旦事务关闭,Hibernate 将发挥它的魔力并更新我们拥有的用户实体的名称。 但是,在这种情况下,我真的不需要将 Harry db 行解析为实体图,将 Harry 加载到应用程序上下文中,而且我绝对不需要为 Harry 急切加载的关系执行所有这些操作。

所以问题来了——我能以某种方式避免这种情况吗? 理想情况下,我希望 Harry 成为一个延迟加载的对象,在调用 setName 方法时添加一个更新查询,该查询将在事务提交后执行。

我目前正在使用 Spring boot 2.0 堆栈,但我的问题适用于任何其他版本和使用 java 的 ORM 方法。

【问题讨论】:

    标签: java hibernate spring-data-jpa spring-data


    【解决方案1】:

    如果我理解正确,我会想到这些选项:

    1 - 显而易见的一个 - 根本不加载 User,只需自己执行更新查询 (UPDATE user SET name = 'Harry' WHERE id = :userId) - 实现此目的的方法的数量,命名查询,带有注释的 spring 方法等。

    2 - 在EntityManager 中有一个getReference 方法,它允许您获取User 代理,只填充它的ID,除非您对其执行一些操作,然后加载字段。它对您发布的简单案例没有帮助,但是如果您的 User 与其他实体有关系,那么您可以从中受益 - 看看 this,这是一个完美的解释

    【讨论】:

    • 轰隆隆!谢谢Shadov,getReference解决方案完美运行,我写成小单元测试并判断SQL日志,hibernate从不实际加载实体,如果我只更新字段,它会生成更新查询,正如我想要的那样,它不是完全完美,因为它生成的更新不仅包括我更新过的所有实体字段,而且仍然好得多。
    • 嗯,虽然你可能对 Hibernate 实际上确实从数据库加载实体的事实是正确的,如果应用了任何更改,这就是为什么认为它可能是这种情况,即使没有 SQL 日志关于它执行这样的操作 - 我注意到如果我设置的字段值等同于保存在数据库中的字段值,它不会记录更新查询,并且除了实际从数据库优先。
    猜你喜欢
    • 2013-02-10
    • 2018-11-22
    • 2011-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多