Java 在hibernate中更新对象的字段

Java 在hibernate中更新对象的字段,java,hibernate,merge,save,Java,Hibernate,Merge,Save,我有一个对象a,它映射到数据库中的表a class A { Integer id; String field2,field2;field3 ,... fieldN; //lots of other attribute } 现在我想编写一个只更新单个字段的DAOAPI。一种方法是首先加载对象,然后更改所需的属性,然后使用合并api //start transcation A a = session.load(A.class, id); A.setfieldP(new

我有一个
对象a
,它映射到数据库中的
表a

class A {
     Integer id;
     String field2,field2;field3 ,... fieldN;
     //lots of other attribute
}
现在我想编写一个只更新单个字段的DAOAPI。一种方法是首先加载对象,然后更改所需的属性,然后使用合并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) 我可以使用更新而不是合并吗?

我通常更喜欢session.get vs session.load,作为session.get而不是抛出异常,但这取决于您想要的行为

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

 session.merge(myObject)
是标准方式,但也可以使用

 session.saveOrUpdate(myObject)
只要对象没有被分离,在您的情况下,它就不会被分离。解释merge和saveOrUpdate的区别


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

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

Query query = session.createQuery("update EntityName set fieldP = 'newValue' "
        + "where id IN (75, 76)");
query.executeUpdate();
这允许您更改字段值,而无需将实体加载到内存中


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

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

使用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();
CriteriaBuilder=session.getCriteriaBuilder();
CriteriaUpdate criteria=builder.createCriteriaUpdate(User.class);
Root=criteria.from(User.class);
criteria.set(root.get(“fname”)、user.getName();
criteria.set(root.get(“lname”),user.getlastName();
其中(builder.equal(root.get(“id”)、user.getId());
createQuery(条件).executeUpdate();

您可能已经知道这一点,但saveOrUpdate确实适用于分离的对象。只有当会话中附加了具有相同id的现有对象时,您才会遇到问题。
saveOrUpdate
将更新db(+1)中现有对象的值@Russ Sanwald:在第二种方法中,我试图做的是,我想更新一个对象。现在要更新它,我不想从db中获取它然后更新,而是创建一个新对象a,设置它的主键和字段N,然后更新。我设置主键,因为我想用primarykey=X更新对象(假设id为x的对象已经存在于数据库中,并且我设置了fieldN以更新它。我没有更改主键,但我的目的是更改id为A的对象的fieldN的值。)=X@akshay:您可以使用更新查询更新对象,而无需将其加载到内存中。请参阅我的答案。@Russ and all:如果我不想使用quesry,请参阅我的ap方法1完全正确?这可以被认为是这个问题的主题之外。我不同意。首先,他要求使用不同的方法(如果有)。其次,从他的第二个代码片段中可以清楚地看出,他希望避免将实体加载到内存中。是否有必要先从数据库中获取对象,然后再更新。如果我实例化一个新对象,该怎么办在我的方法2中,所有未设置的字段都存储为空值,我希望它应该保留旧的not null值