【问题标题】:Which is the better way of using Hibernate seesion.delete() - Delete by Id or delete by object?使用 Hibernate seesion.delete() 的更好方法是按 ID 删除还是按对象删除?
【发布时间】:2018-12-17 02:25:20
【问题描述】:

我正在开发一个使用 Spring MVC 构建的应用程序,它使用 Hibernate 与数据存储进行交互。当我尝试实现删除功能时,我发现有多种方法可以实现 session.delete()。总之,我很困惑以下两种方法中哪一种是实现 Hibernate seesion.delete() 的更好方法(更具体地说,标准方法)。

由于这个API调用在未来阶段会变成微服务,我想这是从网络获取userId而不是整个对象的标准方式。

方法一:

@Transactional    
public void deleteUser(User user) {
    sessionFactory.getCurrentSession().delete(user);
}

方法二:

@Transactional
public void deleteUser(int userId) {
    Query q = session.createQuery("delete User where id = :userId");
    query.setParameter("userId", userId);
    q.executeUpdate();
}

方法三:

@Transactional
public void deleteOrg(int userId) {
    User user = sessionFactory.getCurrentSession().get(User.class, userId);
    sessionFactory.getCurrentSession().delete(user);
}

【问题讨论】:

  • 我越来越糊涂了。您的回答与@Guillaume 的回答相冲突。

标签: spring hibernate spring-mvc spring-boot hibernate-session


【解决方案1】:

Gauillaume F. 回答的更多细节。我建议使用方法 4(高效、可公开的服务以及 Hibernate 的惯用用法)。

方法一

@Transactional    
public void deleteUser(User user) {
    sessionFactory.getCurrentSession().delete(user);
}
  • 删除与会话缓存同步
  • user 必须是 Hibernate 控制下的实例。所以它不能直接暴露为服务。
  • 足够高效。这取决于首先如何检索实例。

方法二

@Transactional
public void deleteUser(int userId) {
    Query q = session.createQuery("delete User where id = :userId");
    query.setParameter("userId", userId);
    q.executeUpdate();
}
  • 高效(没有实例从数据库加载或放入会话缓存)
  • 可以直接作为服务公开
  • 未与会话缓存同步
  • 不必要地使用 HQL

方法3

@Transactional
public void deleteOrg(int userId) {
    User user = sessionFactory.getCurrentSession().get(User.class, userId);
    sessionFactory.getCurrentSession().delete(user);
}
  • 足够高效(实例先从数据库加载,放入会话缓存,然后删除)
  • 可以直接作为服务公开
  • 与会话缓存同步

方法四

@Transactional
public void deleteOrg(int userId) {
    User user = sessionFactory.getCurrentSession().load(User.class, userId);
    sessionFactory.getCurrentSession().delete(user);
}
  • 高效(不加载数据;而是将代理放入会话缓存中)
  • 可以直接作为服务公开
  • 与会话缓存同步

【讨论】:

    【解决方案2】:

    第二种方法不好,因为 Hibernate 无法判断对象已被删除;它可能会对其内部会话缓存产生问题。

    第一种和第三种方法非常相似。您应该使用 load(..) 而不是 get(User.class, userId),因为它返回代理对象而不是获取数据,因此速度更快。

    【讨论】:

    • q.executeUpdate();返回 int 值(0 或 1),表示查询是否成功执行。
    • 是的@DharitaChokshi,但问题不在于 能够判断该行是否已被删除,而在于 Hibernate 的会话缓存。
    • 是的,你是对的。在这种情况下,我更加困惑。您的回答与@locus2k 的回答相冲突。
    • 其实并不矛盾,Locus 也是对的。实体被标记为删除,只有在事务关闭时才会提交。除了第二种情况,因为您绕过 Hibernate 并立即将其删除。它确实“更快”,但对于更复杂的事务也会导致会话缓存出现很多问题,这就是我不推荐这种方法的原因。
    猜你喜欢
    • 2018-11-13
    • 1970-01-01
    • 2013-02-26
    • 1970-01-01
    • 1970-01-01
    • 2017-01-04
    • 2018-08-16
    • 1970-01-01
    • 2016-09-29
    相关资源
    最近更新 更多