增删改查API:
增:session.save()
删:session.delete()
改:session.update()
查:session.get()或session.load()
使用这些API能完成数据库的增删改查,不过Hibernate拥有强大的缓存机制可以跳过这些API完成增删改查。
首先,我们需要了解在Hibernate中的三种状态:
1.瞬时状态 2.持久化状态 3.托管状态
这三种状态与session的缓存有着密切关系
瞬时状态就是刚new出来一个对象,还没有被保存到数据库中,持久化状态就是已经被保存到数据库中,托管状态就是数据库中有,但是session中不存在该对象,区分是否在数据库之中的关键词是是否有对应的主键。
public void First() {
Configuration configure = new Configuration().configure();
SessionFactory SessionFactory = configure.buildSessionFactory();
Session session = SessionFactory.openSession();
Transaction Transaction = session.beginTransaction();
//增加一个班级
ClassRoom room=new ClassRoom();
room.setClassname("3班");
//这里是瞬时状态
session.save(room);
//room进入session缓存中,与session关联
room.setClassname("2班");
Transaction.commit();
session.close();
//session关闭,清理缓存room与session失去联系,变为托管状态
room.setClassname("4班");
}
这个程序说明了三种状态的变化,那么程序执行的结果是什么?
控制台输出的sql语句是
Hibernate: insert into ClassRoom (classname) values (?)
Hibernate: update ClassRoom set classname=? where cid=?
数据库进行了save和update操作。
运行结果是
程序运行的流程:
执行
ClassRoom room=new ClassRoom();
room.setClassname("3班");
//这里是瞬时状态
session.save(room);
处于瞬时状态的room,通过session.save()方法进入session缓存,同时session还为room对象进行了copy放入快照区。
room.setClassname("2班");
Transaction.commit();
room改变classname属性,事务提交,开始进行数据库操作。首先先在数据库insert快照区的room对象,然后再比较缓存区和快照区之间的是否有改变,如果有改变则进行update操作修改。
session.close();
//session关闭,清理缓存room与session失去联系,变为托管状态
room.setClassname("4班");
事务提交后,关闭session,session的缓存也得之清理,room失去了与session的联系,由持久化状态变为托管状态。
之后room对象无论进行什么操作都与session无关,自然和数据库操作无关。
结论:对象是持久化状态与对象是否进入session缓存区有关。
关于session的缓存有以下几个重要API:
session.clear() session.evirt() session.flush()
session.clear()就是清除session的所有缓存:
Session session = SessionFactory.openSession();
Transaction Transaction = session.beginTransaction();
ClassRoom room=new ClassRoom();
room.setClassname("3班");
session.save(room);
session.clear();
//这一步之后,session清理了缓存,room直接变成了托管状态
room.setClassname("2班");
Transaction.commit();
session.close();
执行结果是:
简单的查找操作:
public void Search() {
Configuration configure = new Configuration().configure();
SessionFactory SessionFactory = configure.buildSessionFactory();
Session session = SessionFactory.openSession();
Transaction Transaction = session.beginTransaction();
ClassRoom room=session.get(ClassRoom.class, 1);//类对象类属性,id值
System.out.println(room.toString());
Transaction.commit();
session.close();
}
结果:
Hibernate: select classroom0_.cid as cid1_0_0_, classroom0_.classname as classnam2_0_0_ from ClassRoom classroom0_ where classroom0_.cid=?
ClassRoom [cid=1, classname=1班]
删除操作:
数据库: 目标是删去多余的三班
public void Delete() {
Configuration configure = new Configuration().configure();
SessionFactory SessionFactory = configure.buildSessionFactory();
Session session = SessionFactory.openSession();
Transaction Transaction = session.beginTransaction();
ClassRoom room=session.get(ClassRoom.class, 4);//类对象类属性,id值
session.delete(room);
Transaction.commit();
session.close();
}
熟悉了Hibernate的缓存机制可以知道update操作交由持久化状态处理相当的方便,那么update方法是否显得多余。
update有一个重要的操作就是 将托管状态转化为持久态。
三种状态转化图:
update演示:
当前数据库: 目标将多余的3班改为4班
public void update() {
Configuration configure = new Configuration().configure();
SessionFactory SessionFactory = configure.buildSessionFactory();
Session session = SessionFactory.openSession();
Transaction Transaction = session.beginTransaction();
ClassRoom room=new ClassRoom();
room.setCid(5);//设置了id,room为托管状态
session.update(room);//由此room变为了持久化状态
room.setClassname("4班");
Transaction.commit();
session.close();
}
执行结果:
Hibernate: update ClassRoom set classname=? where cid=?
上面讲的查询方法操作过于单一,下面介绍高级的查询方法。
HQL查询,HQL是hibernate专门用于查询数据的语句,有别于SQL,HQL跟接近于面向对象的思维方式。
@Test
public void Query() {
Configuration configure = new Configuration().configure();
SessionFactory SessionFactory = configure.buildSessionFactory();
Session session = SessionFactory.openSession();
Transaction Transaction = session.beginTransaction();
org.hibernate.Query query=session.createQuery("from ClassRoom where classname=?");
query.setString(0, "3班");
ClassRoom Result = (ClassRoom) query.uniqueResult();
System.out.println(Result);
Transaction.commit();
session.close();
}
执行结果:
Hibernate: select classroom0_.cid as cid1_0_, classroom0_.classname as classnam2_0_ from ClassRoom classroom0_ where classroom0_.classname=?
ClassRoom [cid=3, classname=3班]
使用Criteria进行数据查询:Criteria 完全是面对对象在进行数据查询,将不再看到有sql语句的痕迹
@Test
public void Criteria() {
Configuration configure = new Configuration().configure();
SessionFactory SessionFactory = configure.buildSessionFactory();
Session session = SessionFactory.openSession();
Transaction Transaction = session.beginTransaction();
org.hibernate.Criteria cr= session.createCriteria(ClassRoom.class);
List<ClassRoom> classrooms = cr.list();
for(ClassRoom room:classrooms) {
System.out.println(room);
}
Transaction.commit();
session.close();
}
执行结果:
Hibernate: select this_.cid as cid1_0_0_, this_.classname as classnam2_0_0_ from ClassRoom this_
ClassRoom [cid=1, classname=1班]
ClassRoom [cid=2, classname=2班]
ClassRoom [cid=3, classname=3班]
ClassRoom [cid=5, classname=4班]