本文主要介绍以下三个方面:
1.使用Session-API CRUD操作
2.get()/load()的区别
3.saveOrUpdate()/merge()的区别
1.session.save(obj)
a.当前对象如果是持久态,执行save方法,会发送update语句;
b.当前对象如果是瞬时态,执行save方法,会发送insert语句,对象会从瞬时态转为持久态。
/*session.save(obj);
* 当前对象是持久态时,执行save方法,会执行Update语句
* 当前对象是瞬时态时,执行save方法,会执行insert语句,从瞬时态转换为持久态
* */
@Test
public void testSave() {
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
try {
Students s = new Students();
//s为瞬时态
s.setSname("lisi");
session.save(s);//会执行insert语句,s变成持久态
//Students s = (Students)session.get(Students.class, 1);
//get到的s为持久态
Students s = new Students();
s.setSid(1);
s.setSname("zhangsan2");
session.save(s);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}
}
@Test
public void testSave() {
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
try {
Students s = (Students)session.get(Students.class, 1);
//get到的s为持久态
s.setSid(1);
s.setSname("zhangsan2");
session.save(s);//此时执行update语句
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}
}
2.get()和load()的区别
a.get方法创建对象时首先查询session缓存,没有的话查询二级缓存,最后查询数据库;load方法创建对象时首先查询session缓存,没有的话就创建代理,实际使用数据时才查询二级缓存和数据库;
b.如果找不到符合条件的记录,get方法返回null,而load方法抛出异常(ObjectNotFoundException);
c.使用load方法,一般都是假定你要取得的对象肯定是存在的,而get方法则会去尝试,如果对象不存在,就返回null。
@Test
public void testGet(){
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
try {
//执行get后,变成持久态,立刻发送SQL语句
//Students s = (Students)session.get(Students.class, 1);
Students s1 = (Students)session.get("PersistenceClass.Students", 0);
System.out.println("学号:"+s1.getSid()+"姓名:"+s1.getSname());
//由于s2和s1生成的对象相同,故直接查找session缓存,不再发送SQL语句
Students s2 = (Students)session.get("PersistenceClass.Students", 0);
System.out.println("学号:"+s2.getSid()+"姓名:"+s2.getSname());
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}
}
@Test
public void testLoad(){
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
try {
//执行load后,生成代理对象,当用到对象的属性或者方法时,才发送SQL语句
//Students s = (Students)session.get(Students.class, 1);
Students s1 = (Students)session.load("PersistenceClass.Students", 0);
System.out.println("学号:"+s1.getSid()+"姓名:"+s1.getSname());
//由于s2和s1生成的对象相同,故直接查找session缓存,不再发送SQL语句
Students s2 = (Students)session.load("PersistenceClass.Students", 0);
System.out.println("学号:"+s2.getSid()+"姓名:"+s2.getSname());
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}
}
总结:
a.从两种方法的调试情况可以看出,get每次生成的都是持久态对象,load每次生成的都是代理对象(Students_$$_javassist_0);
b.虽然最后的执行结果相同,但是,load方法只有在使用到对象的属性和方法时,才会发送SQL语句,而get在创建对象时就立刻发送SQL语句。
3.Update()
a.瞬时态不能执行update();
b.持久态和托管态可以执行update();
c.代理对象在session对象关闭后不能执行update()。
@Test
public void testUpdate(){
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
Students s = null;
try {
/*瞬时态对象不能调用update方法
* Students s = new Students();
* s.setSid(2);
* s.setSname("lisi");
* session.update(s);
* */
/*持久化对象可以调用update
* Students s = (Students)session.load("PersistenceClass.Students", 1);
s.setSname("lisi");
session.update(s);*/
s = (Students)session.get(Students.class, 1);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}
/*getCurrentSession()可以在执行try...catch...语句后自动关闭session,此时s变为托管状态*/
//下面重新开启一个session
session = sessionFactory.getCurrentSession();
tx = session.beginTransaction();
s.setSname("wanglaowu");
session.update(s); //s重新变成了持久态
tx.commit();
}
4.从瞬时态转换为持久态,不确定是否存在主键冲突,推荐使用saveOrUpdate()。
@Test
public void testSaveOrUpdate(){
//测试SaveOrUpdate时需要将数据库的主键生成策略改为"assigned"
//从瞬时态转换为持久态,不确定主键是否冲突,推荐使用SaveOrUpdate
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
try {
Students s = new Students();
s.setSid(1);
s.setSname("lisi");
session.saveOrUpdate(s);
/*
* s.getSid(1);
* s.setSname("lisi");
* session.save(s);
* 此时由于主键1已经存在,执行save方法,故会产生主键冲突
*
* */
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}
}
5.delete()
a.持久态或者托管态可以执行delete();
b.瞬时态可以执行delete(),但是Hibernate并不推荐使用delete()删除瞬时态对象,因为这样做没有任何意义。
@Test
public void testDelete(){
//持久态或者托管态可以执行delete方法
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
try {
Students s = (Students)session.get(Students.class, 1);
session.delete(s);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}
}
6.Merge()
a.使用merge方法,如果数据库中有该记录,则更新该记录,如果不存在该记录,则进行insert操作。使用saveOrUpdate()的话和此方法相同;
b.执行完merge(obj)返回一个持久化对象的引用,而实参obj本身还是托管状态的;
c.saveOrUpdate()后的对象会纳入session的管理,对象的状态会跟数据库同步,再次查询该对象会直接从session中取,merge后的对象不会纳入session管理,再次查询该对象还是会从数据库中取。
@Test
public void testMerge(){
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
try {
Students s1 = new Students();
s1.setSid(1);
s1.setSname("lisi");
Students s2 = (Students)session.merge(s1);
System.out.println(s1.hashCode());//s1还是托管的
System.out.println(s2.hashCode());//s2是持久化的
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}
}