【问题标题】:updating a field of a object in hibernate在休眠中更新对象的字段
【发布时间】:2011-10-11 01:27:58
【问题描述】:

我有一个object A 映射到数据库中的table A

class A {
     Integer id;
     String field2,field2;field3 ,... fieldN;
     //lots of other attribute
}

现在我想编写一个只更新单个字段的 DAO api。一种方法是我可以先加载对象,然后更改我需要的属性,然后使用合并 api

//start transcation
A a = session.load(A.class, id);
A.setfieldP(newValue)
session.merge(A)
//commit transcation

现在如果我使用以下代码

 //start transcation
 A a = new A();
 a.setId(id); //set a id by which object A exists in DB
 A.setfieldP(newValue)
 session.merge(A)
 //commit transaction

现在第二种方法除了 id 和 fieldP 之外的所有字段都设置为 null

1)现在还有其他方法吗?
2)我可以使用更新而不是合并吗?

【问题讨论】:

    标签: java hibernate merge save


    【解决方案1】:

    如果您需要一次更新大量实体,最有效的方法是使用查询:

    Query query = session.createQuery("update EntityName set fieldP = 'newValue' "
            + "where id IN (75, 76)");
    query.executeUpdate();
    

    这允许您更改字段值,而无需将实体加载到内存中。

    最好的做法是使用命名查询和命名参数——上面的实现只是一个例子。

    【讨论】:

    • 这可以被认为是这个问题的题外话。
    • 我不同意。首先,他要求采用不同的方法(如果有的话)。其次,从他的第二个代码 sn-p 可以清楚地看出他想避免将实体加载到内存中。
    【解决方案2】:

    我通常更喜欢 session.get 和 session.load,因为 session.get will return null 而不是抛出异常,但这取决于你想要的行为。

    加载对象,设置字段,然后调用任一

     session.merge(myObject)
    

    是标准方式,虽然你也可以使用

     session.saveOrUpdate(myObject)
    

    只要对象没有被分离,在你的情况下,它就不会被分离。 Here is a good article 解释 merge 和 saveOrUpdate 的区别。

    在您的第二个示例中,您正在编辑对象的主键?这通常是不好的形式,您应该删除并插入而不是更改主键。

    【讨论】:

    • 您可能已经知道这一点,但 saveOrUpdate 确实适用于分离的对象。唯一遇到麻烦的情况是会话中附加了具有相同 ID 的现有对象。
    • saveOrUpdate 会将值更新为数据库中的现有对象(+1)
    • @Russ Sanwald:在第二种方法中,我想要更新一个对象。现在为了更新它,我不想从数据库中获取它然后更新,而是创建一个新对象A,设置其主键和字段N,然后更新。我设置主键,因为我想用primarykey = X更新对象(假设ID为x的对象已经存在于DB中,我设置了我想更新的字段N它。我没有更改主键,但我的目的是更改 Id=X 的对象 A 的 fieldN 的值
    • @akshay:您可以使用更新查询更新对象而不将其加载到内存中。看我的回答。
    • @Russ and all:如果我不想使用 quesry,我的方法 1 完全可以吗?
    【解决方案3】:

    使用 JPA,您可以这样做。

    CriteriaBuilder builder = session.getCriteriaBuilder();
    CriteriaUpdate<User> criteria = builder.createCriteriaUpdate(User.class);
    Root<User> root = criteria.from(User.class);
    criteria.set(root.get("fname"), user.getName());
    criteria.set(root.get("lname"), user.getlastName());
    criteria.where(builder.equal(root.get("id"), user.getId()));
    session.createQuery(criteria).executeUpdate();
    

    【讨论】:

      【解决方案4】:

      这里的另一个优化可能是为实体使用设置为 true 的动态更新。这将确保每当有更新时,只有更改的字段才会更新。

      【讨论】:

      • 是否有必要先从 db 获取对象然后更新。如果我用 id X 实例化一个新对象然后只设置我想要更新的字段呢?在我的方法 2 中所有其他字段未设置的存储为空值,我希望它应该保留旧的非空值
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-20
      • 2019-11-14
      • 2013-02-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多