public class Main {
public static void main(String[] args) {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session session=sf.getCurrentSession();
session.beginTransaction();
Product product=(Product) session.get(Product.class,1);
product.setName("xx");
session.save(product);
session.getTransaction().commit();
sf.close();
}
}
这段代码是想更新一下id为1的product的name字段,但是我故意把update方法写成了save方法。结果,控制台打印出的sql语句仍是update:
Hibernate: select product0_.id as id0_0_, product0_.name as name0_0_, product0_.price as price0_0_ from product_ product0_ where product0_.id=?
Hibernate: update product_ set name=?, price=? where id=?
为什么会这样?难道Hibernate知道这个product存在在数据库中,就不管我写的是update还是save,自己就去调用update方法了?如果是这样的话,那Hibernate的作者何必创建这两个方法,一个就够了嘛。
于是我就去查阅了下资料,才知道上面的那行save()完全是多余的,有它没它结果一样。因为 对一个已经持久的对象调用 save() 或 update() 方法是没有意义的。当事务提交时,hibernate会自动按照一定的策略将session中的持久化对象,同步到数据库中,从而自动使数据库的状态和session中的对象状态完全一致。
那如何体现update和save的区别呢?看下面的代码:
public class Main {
public static void main(String[] args) {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session session=sf.getCurrentSession();
session.beginTransaction();
Product product=(Product) session.get(Product.class,1);
product.setName("ll");
session.close();
Session session1=sf.getCurrentSession();
session1.beginTransaction();
session1.save(product);//这里正确的应该是用update()方法
session1.getTransaction().commit();
sf.close();
}
}
session.close()之后,这个product已经不是持久化状态了,而是游离状态,所以当新建session1后,需要用update来更新,而我用了save()方法,save()的作用是将对象从临时状态变成持久化状态,所以它把producut当成临时状态,在数据库新增了一条记录,而不是修改id为1的product。虽然没有报错,但不是我们想要的结果。
上面是应该要用update的情况,再来看应该要用save的例子:
public class Main {
public static void main(String[] args) {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session session=sf.getCurrentSession();
session.beginTransaction();
Product product=new Product();
product.setName("ll");
session.update(product);//这里正确的应该要用save()方法
session.getTransaction().commit();
sf.close();
}
}
这个product既不是持久化状态也不是游离状态,而是临时状态。所以要用save()方法把它变成持久化状态,而我用了update()方法,所以报错了。
那有没有方法可以一石二鸟呢?有的,那就是saveOrUpdate(),上面两个例子都可以用saveOrUpdate()解决。它不用我们考虑对象是从临时状态还是游离状态变成持久状态的,Hibernate会自己判断并且采用对应的save或者是update方法。