Hibernate的基本使用
Hibernate基本配置,工具类
CURD操作
save()
save() 为Hibernate的API,用于持久化
例:
@Test
public void testSave(){
Session session = HibernateUtil.getSession();
try{
//开启事物
session.beginTransaction();
//4.保存对象
Student stu = new Student();
stu.setAge(12);
stu.setName("fafa败");
stu.setScores(55);
session.save(stu);
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
persist()
persist()为JPA的API,用于持久化
例:
@Test
public void testPersist() {
Session session = HibernateUtil.getSession();
try {
//开启事务
session.beginTransaction();
Student stu = new Student();
stu.setAge(12);
stu.setName("阿斯达");
stu.setScores(55);
session.persist(stu);
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
delete()
必须要指定删除对象的ID
例:
@Test
public void testDelete() {
Session session = HibernateUtil.getSession();
try {
//开启事务
session.beginTransaction();
Student stu = new Student();
stu.setId(6);
stu.setAge(12);
stu.setName("asfaa");
stu.setScores(55);
//只与ID有关.与其他属性无关
session.delete(stu);
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
}
}
update()
更新操作,需要指定ID
例:
@Test
public void testUpdate() {
Session session = HibernateUtil.getSession();
try {
//开启事务
session.beginTransaction();
Student stu = new Student();
stu.setId(5);
stu.setAge(12);
stu.setName("asfaa");
stu.setScores(55);
//只与ID有关.与其他属性无关
session.update(stu);
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
}
}
saveOrUpdate()
通过参数对象是否具有ID值来判断实质性save()操作还是update().
若参数对象具有ID,但该ID在DB中不存在,则会抛出异常
例:
@Test
public void testSaveOrUpdate() {
Session session = HibernateUtil.getSession();
try {
//开启事务
session.beginTransaction();
Student stu = new Student();
stu.setId(7);
stu.setAge(12);
stu.setName("aaaaa");
stu.setScores(55);
//只与ID有关.与其他属性无关
session.saveOrUpdate(stu);
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
}
}
get()
查询无果时,放回null,但不会抛出异常.而且查询的时候要开启事务
例:
@Test
public void testGet() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
//查到数据
//Student student = session.get(Student.class, 1);
//查不到数据返回null
Student student = session.get(Student.class, 6666);
System.out.println(student);
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
load()
查不到数据时,会抛出异常
例:
@Test
public void testLoad() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
//查到数据
//Student student = session.load(Student.class, 1);
//查不到数据抛出异常
Student student = session.load(Student.class, 999);
System.out.println(student);
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
注意
1.对于不同操作对象的增 删 改操作,无论代码的书写语句顺序是怎样的,底层SQL的执行都是 insert update delete
若要修改其底层的执行顺序,则可通过Session的flush()方法刷新Session完成
例:
@Test
public void testSaveDeleteUpdate() {
Session session = HibernateUtil.getSession();
try {
//开启事务
session.beginTransaction();
//删除对象
Student deleteStudent = new Student();
deleteStudent.setId(2);
//添加对象
Student saveStudent = new Student();
saveStudent.setAge(11);
saveStudent.setName("adada");
//修改对象
Student updateStudent = session.get(Student.class, 4);
updateStudent.setName("修改");
session.delete(deleteStudent);
//此处可以刷新session的执行顺序
//session.flush();
session.save(saveStudent);
session.update(updateStudent);
session.load(Student.class, 9999);
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
getCurrentSession() 和 openSession() 获取Session的区别
方法名 | 获取的对象 | 对象的关闭 | 环境的注册 | 查询对事物的支持 |
---|---|---|---|---|
getCurrentSession() | 无论执行多少 次 该 方 法 ,只要是在同一线程中,获取的都是同一个session | 自动关闭Session,无需手工关闭 | 需要注册Session的运行环境 | 查询必须在事务内执行 |
openSession() | 每执行一次该方法,获取到的都是一个新的session对象 | 必须手工关闭Session对象 | 无需注册 | 查询可以不在事务内执行 |
Hibernate 对象持久化状态管理
一 . Hibernate 的对象状态
对象的状态一般是指对象的一组属性的值。而这里的状态是指对象处于什么存储介 质 中。用于存放对象的存储介质有三个:普通内存(与 Hibernate 无关)、 Session 缓存、数据 库。对象处于不同的介质,就将处于不同的状态。
二 . 状态转换
1.状态转换图
2、对象状态
(1)暂时态:transient 状态,对象在内存中存在,但 DB 中无记录,与 Session 无关,是个 过渡状态。
(2)持久态:persistent 状态,在内存中存在,DB中有记录,与Session 相关在 Session 中有对象的副本。
(3)游离态:detached 状态,在内存中存在,在 DB 中有记录,与 Session 无关。
(4)无 名态:在内存中不存在,但在 DB 中有记录,与 Session 无关。
3、状态转换常用方法
save( ):将暂时态对象同步到 DB 中。
update( ):将游离态对象同步到 DB 中。
delete( ):将指定的对象从 session 中删除,同时也删除 DB 中的该数 据。
close( ):关闭 Session 对象。
clear( ):清空 Session 的缓存。
saveOrUpdate( ):根据参数对象的 id 属性是否为 null 来判断是执行保存还是更 新操作。
evict():将指定对象仅仅从 session 中删除,但不删除 DB 中的该数 据。
load( )与 get( ):将无名态对象转换为持久态对象
4、Hibernate 的同步机制 Hibernate 中的同步是指刷新缓存,以使缓存与 DB 中数据保持一致。当调用不 同的状 态转换方法后,Session 能够在某些时间点完成缓存的刷新,将缓存中的 持久化对象同步更 新到 DB。这些时间点是执行以下方法: (1)Session 的 flush() (2)事务的 commit()
一、API
1、Query 接口 Hibernate 进行 HQL 查询的接口,支持动态绑定参数的功能。使用 Session 对象 的 createQuery 方法可获取 Query 对象。 Query query = session.createQuery(hql);
2、SQLQuery 接口 Hibernate 进行 SQL 原生查询的接口,支持动态绑定参数的功能,是 Query 接 口的子接 口。使用 Session 对象的 createSQLQuery()方法可获取 SQLQuery 对 象。 SQLQuery sqlQuery = session.createSQLQuery(sql); 其查询出的结果对象默 认为 Object,当然,若结果为 List,则其元素为 Object。使用 SQLQuery 的 addEntity(Xxx.class)方法,可以将其结果泛型设定为指定类型。
3、Criteria 接口 Criteria,标准、准则,Hibernate 进行 Criteria 查询的接口,与 Query 接口无 关。使用 Session 对象的 createCriteria()方法可获取 Criteria 对象。 Criteria criteria = session.createCriteria(Xxx.class);
二、查询示例
Hibernate 是 DAO 层技术,对数据的使用,查询是最为重要的。Hibernate 的 查询技术非常强大,支持原始 SQL 语句查询,支持 QBC 查询及 Hibernate 特 有的 HQL 查询。 HQL,Hibernate Query Language,Hibernate 查询语言,它与 SQL 非常相 似。但,HQL 是面向对象的查询语言,而 SQL 是面向二维表的。HQL 查询语句 中使用的是类名与属性名,而 SQL 语句使用的是表名与字段名。
查询结果list
1.SQL
@Test
public void testSQL1() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
String sql = "select * from t_student1";
List<Student> list = session.createSQLQuery(sql).addEntity(Student.class).list();
for (Student stu : list) {
System.out.println(stu.toString());
}
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
2.HQL
@Test
public void testHQL1() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
String hql = "from Student";
List<Student> list = session.createQuery(hql).list();
for (Student stu : list) {
System.out.println(stu.toString());
}
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
3.QBC
@Test
public void testQBC1() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
List<Student> list = session.createCriteria(Student.class).list();
for (Student stu : list) {
System.out.println(stu.toString());
}
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
查询结果排序
1.SQL
@Test
public void testSQL2() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
String sql = "select * from t_student1 order by tname desc";
List<Student> list = session.createSQLQuery(sql).addEntity(Student.class).list();
for (Student stu : list) {
System.out.println(stu.getName());
}
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
2.HQL
@Test
public void testHQL2() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
String hql = "from Student order by name desc";
List<Student> list = session.createQuery(hql).list();
for (Student stu : list) {
System.out.println(stu.getName());
}
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
3.QBC
@Test
public void testQBC2() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
List<Student> list = session.createCriteria(Student.class).addOrder(Order.desc("name")).list();
for (Student stu : list) {
System.out.println(stu.getName());
}
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
动态参数绑定
1.SQL
//使用"?"占位符占位,setXxx绑定参数,SetXxx(int position,Object value)
//方法名中的Xxx表示该位置参数的类型,position表示第几个占位符,从0开始
@Test
public void testSQL3() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
String sql = "select * from t_student1 where tage > ? and tscores < ?";
List<Student> list = session.createSQLQuery(sql).addEntity(Student.class).setInteger(0, 3).setDouble(1, 50).list();
for (Student stu : list) {
System.out.println(stu.toString());
}
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
//使用setParamter(String name,Object value)方法动态参数绑定,根据别名
@Test
public void testSQL3setParameterByName() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
String sql = "select * from t_student1 where tage > :age and tscores < :score";
List<Student> list = session.createSQLQuery(sql).addEntity(Student.class).setParameter("age", 3).setParameter("score", 50).list();
for (Student stu : list) {
System.out.println(stu.toString());
}
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
//使用setParamter(int position,Object value)方法动态参数绑定,根据占位符
@Test
public void testSQL3setParameter() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
String sql = "select * from t_student1 where tage > ? and tscores < ?";
List<Student> list = session.createSQLQuery(sql).addEntity(Student.class).setParameter(0, 3).setParameter(1, 50).list();
for (Student stu : list) {
System.out.println(stu.toString());
}
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
2.HQL
//以上三种方式均可实现,用法相同
@Test
public void testHQL3() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
String hql = "from Student where age > ? and scores < ?";
List<Student> list = session.createQuery(hql).setParameter(0, 2).setParameter(1, 59.2).list();
for (Student stu : list) {
System.out.println(stu.toString());
}
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
3.QBC
//需要向Criteria对象添加限制条件 Restrictions,即添加查询条件
//Restriction 中文意思:限制,约束 Restrictions具有很多静态方法可用于
//表示关系比较
@Test
public void testQBC3() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
List<Student> list = session.createCriteria(Student.class).add(Restrictions.gt("age", 2)).add(Restrictions.lt("scores", 50.0)).list();
for (Student stu : list) {
System.out.println(stu.toString());
}
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
分页查询
1.SQL
@Test
public void testSQL4() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
String sql = "select * from t_student1 limit ? , ?";
List<Student> list = session.createSQLQuery(sql).addEntity(Student.class).setParameter(0, 3).setParameter(1, 5).list();
for (Student stu : list) {
System.out.println(stu.toString());
}
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
2.HQL
//Query 接口中具有 setFirstResult()方法
//用于设置从总查询结果集的第几条记录 作为本查询结果子集的开始
//即本页的开始。总查询结果集从 0 开始记数。
//而 setMaxResults()方法用于设置该页所包含的记录数。
@Test
public void testHQL4() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
String hql = "from Student";
List<Student> list = session.createQuery(hql).setFirstResult(3).setMaxResults(5).list();
for (Student stu : list) {
System.out.println(stu.toString());
}
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
3.QBC
//Criteria 接口中也有 setFirstResult()与 setMaxResults()方法,
//其用法与意义与 Query 接口中的完全相同。
//由于 Criteria 与 Query 接口无关,
//所以这两组完全相 同的方法也是没有关系的,仅仅是写法与用法相同而已
@Test
public void testQBC4() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
List<Student> list = session.createCriteria(Student.class).setFirstResult(3).setMaxResults(5).list();
for (Student stu : list) {
System.out.println(stu.toString());
}
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
模糊查询
1.SQL
@Test
public void testSQL5() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
String sql = "select * from t_student1 where tname like :sname";
List<Student> list = session.createSQLQuery(sql).addEntity(Student.class).setParameter("sname", "%萧%").list();
for (Student stu : list) {
System.out.println(stu.toString());
}
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
2.HQL
@Test
public void testHQL5() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
String hql = "from Student where name like :sname";
List<Student> list = session.createQuery(hql).setParameter("sname", "%萧%").list();
for (Student stu : list) {
System.out.println(stu.toString());
}
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
3.QBC
@Test
public void testQBC5() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
List<Student> list = session.createCriteria(Student.class).add(Restrictions.like("name", "%萧%")).list();
for (Student stu : list) {
System.out.println(stu.toString());
}
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
唯一性查询
1.SQL
//SQLQuery 接口的uniqueResult()方法表示其查询结果为一条数据,其返回值为Object
@Test
public void testSQL6() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
String sql = "select * from t_student1 where tid = ?";
Student student = (Student) session.createSQLQuery(sql).addEntity(Student.class).setParameter(0, 3).uniqueResult();
System.out.println(student.toString());
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
2.HQL
@Test
public void testHQL6() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
String sql = "from Student where id = ?";
Student student = (Student) session.createQuery(sql).setParameter(0, 3).uniqueResult();
System.out.println(student.toString());
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
3.QBC
@Test
public void testQBC6() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
Student student = (Student) session.createCriteria(Student.class).add(Restrictions.eq("id", 5)).uniqueResult();
System.out.println(student.toString());
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
聚合函数查询
1.SQL
@Test
public void testSQL7() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
String sql = "select count(*) from t_student1";
Object o = session.createSQLQuery(sql).uniqueResult();
System.out.println(o);
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
2.HQL
@Test
public void testHQL7() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
String sql = "select count(*) from Student";
Object o = session.createQuery(sql).uniqueResult();
System.out.println(o);
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
3.QBC
//Projection 中文意思:投影 Projections中包含很多聚合函数的静态方法
@Test
public void testQBC7() {
Session session = HibernateUtil.getSession();
try {
session.beginTransaction();
Object id = session.createCriteria(Student.class).setProjection(Projections.count("id")).uniqueResult();
System.out.println(id);
session.beginTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.beginTransaction().rollback();
}
}
投影查询
1.SQL
//要求查询的字段别名要与实体类的属性名相同,这样才能将结果转换为相应类的对象
@Test
public void testSQL8() {
Session session = HibernateUtil.getSession();
session.beginTransaction();
String sql = "select tname name,tage age from t_student1";
List<Student> list = session.createSQLQuery(sql).setResultTransformer(Transformers.aliasToBean(Student.class)).list();
//aliasToBean()方法首先创建一个空的Student对象,然后会将别名
//与Student属性名对比,再用查询出的值初始化创建的Student对象
for (Student student : list) {
System.out.println(student.toString());
}
session.beginTransaction().commit();
}
2.HQL
//HQL查询要求实体类中具有相同投影作为参数的带参构造器,所以,首先要
//在Student类中添加相应的带参构造器
@Test
public void testHQL8() {
Session session = HibernateUtil.getSession();
session.beginTransaction();
String sql = "select new Student(name,age) from Student";
List<Student> list = session.createQuery(sql).list();
for (Student student : list) {
System.out.println(student.toString());
}
session.beginTransaction().commit();
}
3.QBC
@Test
public void testQBC8() {
Session session = HibernateUtil.getSession();
session.beginTransaction();
//指定name和age属于为投影
ProjectionList projectionList = Projections.projectionList()
.add(Projections.alias(Projections.property("name"), "name"))
.add(Projections.alias(Projections.property("age"), "age"));
List<Student> list = session.createCriteria(Student.class).setProjection(projectionList)
.setResultTransformer(Transformers.aliasToBean(Student.class)).list();
//setResultTransformer()的方法参数Transformers.aliasToBean()会根据别名
//自动创建指定类型对象
for (Student student : list) {
System.out.println(student.toString());
}
session.beginTransaction().commit();
}
分组查询
1.SQL
//实现查询所有年龄段,及人数多于1人的年龄段
@Test
public void testSQL9() {
Session session = HibernateUtil.getSession();
session.beginTransaction();
String sql = "select tage from t_student1 group by tage";
List<Object> list = session.createSQLQuery(sql).list();
for (Object o : list) {
System.out.println(o);
}
System.out.println("============");
String sql1 = "select tage from t_student1 group by tage having count(tage)>?";
List<Object> list1 = session.createSQLQuery(sql1).setParameter(0, 1).list();
for (Object o : list1) {
System.out.println(o);
}
session.beginTransaction().commit();
}
2.HQL
@Test
public void testHQL9() {
Session session = HibernateUtil.getSession();
session.beginTransaction();
String hql = "select age from Student group by age";
List<Object> list = session.createQuery(hql).list();
for (Object o : list) {
System.out.println(o);
}
System.out.println("============");
String hql1 = "select age from Student group by age having count(age)> ?";
//此处有一个疑问setParameter无法使用
List<Object> list1 = session.createQuery(hql1).setInteger(0, 1).list();
for (Object o : list1) {
System.out.println(o);
}
session.beginTransaction().commit();
}
3.QBC
@Test
public void testQBC9() {
//QBC不支持having
Session session = HibernateUtil.getSession();
session.beginTransaction();
List<Object> age = session.createCriteria(Student.class).setProjection(Projections.groupProperty("age")).list();
for (Object o : age) {
System.out.println(o);
}
session.beginTransaction().commit();
}
Query的list()和iterate()的区别
list和iterate的区别
使用Query接口的list()与iterate()进行查询,查看其控制台的SQL语句的输出情况,可以看到它们的区别主要有两点:
1.使用list()会一次性将所有符合条件的记录查询出来,而使用iterate(),则会先查询出所有符合条件的记录的id,然后再根据id逐个查询出记录的具体内容。
2.使用list(),不会使用缓存机制,即每次执行一次查询代码,控制天均会执行一次SQL查询语句,而使用iterate(),则会使用缓存机制,只有第一次会执行SQL查询,再往后的查询会直接从缓存中读取。
N+1问题
使用Query的iterate()方法虽然使用了Hibernate 的缓存机制,但同时也出现了N+1问题在第一次查询出了所有满足条件的 id 后,会根据这些id逐条从缓存中进行详情查询。
在逐条查询时,缓存中肯定没,然后会到 DB 中查询。在第二次查询时,仍会先执行一次满足条件的id的查询。
然后再到缓存中根据id查询详情这就是N+1问题,N+1问题其实是指,与 list()查询相比多执行了多少次查询:
多执行了N+1次。N次根据id所进行的查询,1次第二次进行的满足条件的id查询。
N+1问题的避免
要避免N+1问题,就要保证缓存中有数据,这样即可以利用缓存,又可以避免N+1问题。
所以,可以在第一次查询时使用 list(),而以后的查询则使用iterate()。
Query的list()查询
@Test
public void testHQL10_list() {
Session session = HibernateUtil.getSession();
session.beginTransaction();
String hql = "from Student";
//第一次查询
List<Student> list = session.createQuery(hql).list();
for (Student student : list) {
System.out.println(student.toString());
}
//第二次查询
List<Student> list1 = session.createQuery(hql).list();
for (Student student : list1) {
System.out.println(student.toString());
}
session.beginTransaction().commit();
}
Query的iterate()查询
@Test
public void testHQL10_list_iterate() {
Session session = HibernateUtil.getSession();
session.beginTransaction();
String hql = "from Student";
//第一次查询
Iterator<Student> list = session.createQuery(hql).iterate();
while (list.hasNext()) {
Student student = list.next();
System.out.println(student.toString());
}
//第二次查询
Iterator<Student> list1 = session.createQuery(hql).iterate();
while (list1.hasNext()) {
Student student = list1.next();
System.out.println(student.toString());
}
session.beginTransaction().commit();