1.Update和Merge的一个小区别总结
Update方法:如果要更新的对象是持久态而且在DirtyCheck的时候没有发现改变,那么就不发Update语句。如果更新的对象是游离态即使对象没有改变,也会发Update语句的。
Merge方法:无论更新对象是什么状态(游离态或持久态)只要DirtyCheck的时候没有对象改变,那么就不会发Update语句,但是如果是游离态的对象,它们会有一条query语句取对象。
dirtyCheck的相关类方法如下:
DefaultFlushEntityEventListener.dirtyCheck() DirtyCheckContextImpl
2.测试
Case1: Update方法
代码如下
public void testInsert() {
log.info("Starting to run testInsert...");
Session session = this.getSession();
Transaction tx = session.beginTransaction();
Product product = new Product("iPhone 10", 4455);
session.save(product);
tx.commit();
session.close();
Product p = new Product(product.getName(), product.getPrice());
p.setId(product.getId());
Session session1 = this.getSession();
log.info("Starting to run testInsert...");
tx = session1.beginTransaction();
session1.update(p);
// session1.merge(p);
tx.commit();
session1.close();
}
执行结果如下,可以看到虽然Product这个类没有什么改变但是还是发出了Update语句。
Hibernate: insert into products (name, price, id) values (?, ?, ?)
2022-04-06_16:48:03.974 INFO com.beans.TempleteTest - Starting to run testInsert...
Hibernate: update products set name=?, price=? where id=?
Case2 : Merge方法
如果把上面的代码改一下,改动如下:
//?? ??? ?session1.update(p);
?? ??? ?session1.merge(p);
执行结果如下,可以看到Merge方法是如果对象是游离状态时,先在数据库里取一对象,然后做个对比。如果有改变在发update语句,如果没有,就不发Update语句了。
Hibernate: insert into products (name, price, id) values (?, ?, ?)
2022-04-06_16:53:25.408 INFO com.beans.TempleteTest - Starting to run testInsert...
Hibernate: select product0_.id as id1_0_0_, product0_.name as name2_0_0_, product0_.price as price3_0_0_ from products product0_ where product0_.id=?
Case3 : Merge方法
public void testInsert2() {
log.info("Starting to run testInsert...");
Session session = this.getSession();
Transaction tx = session.beginTransaction();
Product product = new Product("iPhone 10", 4455);
session.save(product);
tx.commit();
Product p = new Product(product.getName(), product.getPrice());
p.setId(product.getId());
log.info("Starting to run testInsert...");
tx = session.beginTransaction();
// session1.update(p);
session.merge(p);
tx.commit();
session.close();
}
执行结果如下:可以看到同一个Session情况下,Merge和Update方法是不用取product对象了,因为它是持久状态了。
Hibernate: insert into products (name, price, id) values (?, ?, ?)
2022-04-06_16:58:01.206 INFO ?com.beans.TempleteTest - Starting to run testInsert...
|