前言:上一篇文章给大家介绍了Hibernate的简单使用,这里给大家介绍Hibernate相关部分的详细讲解。
一、持久化对象三种状态:
1、瞬时态:无id,未与session关联
2、持久态:有id,与session有关联
3、游离|托管态:有id,未与session关联
public class TestState {
/**
* 通过代码展示对象状态的转换过程
*/
@Test
public void fun1() {
Session session = HibernateUtil.openSession();
Transaction transaction = session.beginTransaction();
Grades grades = new Grades();//瞬时态 无id,与session未关联
grades.setS_class("302");//瞬时态
//save方法可以理解成将瞬时态转为持久态,生成id
session.save(grades);//持久态 有id,与session有关联
transaction.commit();
session.close();//托管|游离态 有id,与session未关联
}
/**
* 持久态特点:能自动更新数据库
*/
@Test
public void fun2() {
Session session = HibernateUtil.openSession();
Transaction transaction = session.beginTransaction();
//根据主键去获取对象,此时的对象是持久化状态
Grades grades = session.get(Grades.class, 2L);
//这里并没有调用update方法,但是却能更新数据库,这里面因为Hibernate存在一级缓存
grades.setS_name("new name");
transaction.commit();
session.close();
}
}
对象状态.png
二、Hibernate的一级缓存:
即session的缓存,是一块内存空间,用来存放对应的java对象。通过hibernate查询对象时,优先根据OID从缓存中查找,减少对数据库的访问次数。
特点:
1、当调用session的save(),update(),saveOrUpdate()方法时,如果缓存中没有对应的对象,就会从数据库中查对应的数据并存到一级缓存中;
2、当调用session接口的load(),get()或者Query接口的list(),iterator()方法时,会先从缓存中找该对象,有则返回,没有就查找数据库,并存在一级缓存中;
3、当调用session的close()方法时,session缓存将被清空
/**
* 测试Hibernate的一级缓存
*/
public class TestSession {
@Test
public void fun1() {
Session session = HibernateUtil.openSession();
Transaction transaction = session.beginTransaction();
Grades grades1 = session.get(Grades.class, 1L);//通过sql查询数据库,并将该对象存到session缓存中
System.out.println(grades1);
Grades grades2 = session.get(Grades.class, 1L);//直接从session缓存中获取
System.out.println(grades2);
System.out.println(grades1 == grades2);//true 一级缓存存的是对象地址
transaction.commit();
session.close();
}
}
日志.png
一级缓存的内部结构:(快照区)
image.png
当Hibernate向一级缓存存入数据时,会同时存入相同数据到快照区,这个时候会通过对象进行一些操作。当提交事务后,会通过OID去判断缓存中的数据和快照区的是否一致(判断对象是否有修改,是否需要更新数据库),如果对象的属性发生了变化,这个时候就需要执行update语句,将缓存中的数据同步到数据库,并更新快照;否则不做任何操作。快照的作用就是为了确保一级缓存中的数据和数据库保持一致,并且减少了了数据库的访问次数。
三、Hibernate中的事务
1、事务特性:
a)原子性:事务中所有的操作是一个不可分割的单元,要么全部执行,要么全部不执行
c)一致性:事务完成时,所有的数据都保持一致的状态
i)隔离性:并发执行的各个事务之间不能相互干扰
d)持久性:事务提交后,对数据库的数据改变是永久性的,提交后的其他操作或故障不会对其有影响
2、事务的并发问题:
a)脏读 :一个事务读取到另一个事务未提交的数据
b)不可重复读:一个事务读到了另一个事务应该提交的update数据,导致同一事务中多次查询结果不一致
c)虚读|幻读 :一个事务读到了另一个事务应该提交的insert数据,导致同一事务中多次查询结果不一致
3、事务的隔离级别:
为了避免事务并发问题,SQL定义了4个事务隔离级别
a)读未提交 1 READ_UNCOMMITTED:可以读取还未提交的事务的数据,会产生a,b,c并发问题
b)读已提交 2 READ_COMMITTED:可以读取事物提交后的数据,会产生b,c并发问题
c)可重复读 4(mysql默认隔离级别,实际开发中选择 )REPEATABLE_READ:可以读取其他事物提交的新插入的数据,会产生c并发问题
d)序列化/串行化 8 SERIALIZABLE: 不会出现并发问题
4、Hibernate的事务管理 :
在hibernate.cfg.xml中配置:
<!--
指定hibernate操作数据库时的隔离级别
## specify a JDBC isolation level
#hibernate.connection.isolation 1|2|4|8
0001 1 读未提交
0010 2 读已提交
0100 4 可重复读
1000 8 串行化
-->
<property name="hibernate.connection.isolation">4</property>
为了确保Service层和Dao层使用的是同一个Session对象,可以通过getCurrentSession()来获取,获取的session不用关闭,线程执行结束后,会自动关闭。Hibernate通过ThreadLocal将Session绑定到了当前线程中,需要在hibernate.cfg.xml中添加配置:
<!--指定session与当前线程绑定-->
<property name="hibernate.current_session_context_class">thread</property>
四、Hibernate中的批量查询
1、HQL(多表,但不复杂时使用):Hibernate创建的面向对象查询语句
/**
* HQL查询
*/
public class TestHqlQuery {
/**
* 基本查询
*/
@Test
public void hql() {
String hql = "from Grades";
Session currentSession = HibernateUtil.getCurrentSession();
Transaction transaction = currentSession.beginTransaction();
try {
Query query = currentSession.createQuery(hql);
List<Grades> list = query.list();
System.out.println(list.size());
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
}
transaction.commit();
}
/**
* 通过命名占位符进行条件查询
*/
@Test
public void hql2() {
String hql = "from Grades where id = :id";
Session currentSession = HibernateUtil.getCurrentSession();
Transaction transaction = currentSession.beginTransaction();
try {
Query query = currentSession.createQuery(hql);
//设置查询参数
query.setParameter("id", 1l);
Grades grades = (Grades) query.uniqueResult();
System.out.println(grades.getS_name());
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
}
transaction.commit();
}
/**
* 模糊查询
*/
@Test
public void hql3() {
String queryName = "小周";
String hql = "from Grades g where g.s_name like :name ";
Session currentSession = HibernateUtil.openSession();
Transaction transaction = currentSession.beginTransaction();
try {
Query query = currentSession.createQuery(hql);
query.setParameter("name", "%" + queryName+"%");
List<Grades> grades = query.list();
System.out.println(grades.toString());
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
}
transaction.commit();
currentSession.close();
}
/**
* 分页查询
*/
@Test
public void hql4() {
String hql = "from Grades";
Session currentSession = HibernateUtil.getCurrentSession();
Transaction transaction = currentSession.beginTransaction();
try {
Query query = currentSession.createQuery(hql);
//设置分页查询参数
query.setFirstResult(0);
query.setMaxResults(5);
List<Grades> grades = query.list();
System.out.println(grades.toString());
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
}
transaction.commit();
}
}
2、Criteria(单表条件查询):Hibernate创建的无语句查询
/**
* Criteria查询
*/
public class TestCriteria {
/**
* 基本查询
*/
@Test
public void fun1() {
Session currentSession = HibernateUtil.getCurrentSession();
Transaction transaction = currentSession.beginTransaction();
Criteria criteria = currentSession.createCriteria(Grades.class);
List<Grades> list = criteria.list();
System.out.println(list);
transaction.commit();
}
/**
* 条件查询
* 对应关系
* > gt
* >= ge
* < lt
* <= le
* == eq
* != ne
* in in
* between and between
* like like
* is not null isNotNull
* is null isNull
* or or
* and and
*/
@Test
public void fun2() {
Session currentSession = HibernateUtil.getCurrentSession();
Transaction transaction = currentSession.beginTransaction();
Criteria criteria = currentSession.createCriteria(Grades.class);
//添加查询条件,查询id=1的成绩
criteria.add(Restrictions.eq("id", 1L));
Grades grades = (Grades) criteria.uniqueResult();
System.out.println(grades);
transaction.commit();
}
/**
* 条件查询,模糊查询
*/
@Test
public void fun3() {
Session currentSession = HibernateUtil.getCurrentSession();
Transaction transaction = currentSession.beginTransaction();
Criteria criteria = currentSession.createCriteria(Grades.class);
//添加查询条件,模糊匹配
criteria.add(Restrictions.like("s_name", "%小周%"));
List<Grades> list = criteria.list();
System.out.println(list.toString());
transaction.commit();
}
/**
* 分页查询
*/
@Test
public void fun4() {
Session currentSession = HibernateUtil.getCurrentSession();
Transaction transaction = currentSession.beginTransaction();
Criteria criteria = currentSession.createCriteria(Grades.class);
//设置分页查询,相当于limit ?,?
//查询前十条数据
criteria.setFirstResult(0);
criteria.setMaxResults(10);
List<Grades> list = criteria.list();
System.out.println(list.toString());
transaction.commit();
}
/**
* 查询总条数
*/
@Test
public void fun5() {
Session currentSession = HibernateUtil.getCurrentSession();
Transaction transaction = currentSession.beginTransaction();
Criteria criteria = currentSession.createCriteria(Grades.class);
//设置查询的聚合韩式->总行数
criteria.setProjection(Projections.rowCount());
Long count = (Long) criteria.uniqueResult();
System.out.println(count);
transaction.commit();
}
}
3、原生SQL:复杂的业务查询
/**
* SQL查询
*/
public class TestSqlQuery {
/**
* 通过命名参数查询
*/
@Test
public void sql1() {
String hql = "select * from grades where id =:g_id";
Session currentSession = HibernateUtil.getCurrentSession();
Transaction transaction = currentSession.beginTransaction();
try {
NativeQuery query = currentSession.createSQLQuery(hql);
query.setParameter("g_id", 1);
//将结果集封装到对象中
query.addEntity(Grades.class);
List<Grades> grades = query.list();
System.out.println(grades.toString());
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
}
transaction.commit();
}
/**
* 模糊查询
*/
@Test
public void sql2() {
String hql = "select * from grades g where g.s_name like ?0";
Session currentSession = HibernateUtil.getCurrentSession();
Transaction transaction = currentSession.beginTransaction();
try {
NativeQuery query = currentSession.createSQLQuery(hql);
query.setParameter(0, "%小周");
//将结果集封装到对象中
query.addEntity(Grades.class);
List<Grades> grades = query.list();
System.out.println(grades.toString());
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
}
transaction.commit();
}
/**
* 基本查询
*/
@Test
public void sql3() {
String hql = "select * from Grades";
Session currentSession = HibernateUtil.getCurrentSession();
Transaction transaction = currentSession.beginTransaction();
try {
NativeQuery query = currentSession.createSQLQuery(hql);
query.addEntity(Grades.class);
List<Grades> grades = query.list();
System.out.println(grades.toString());
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
}
transaction.commit();
}
/**
* 通过JPA占位符进行分页查询
*/
@Test
public void sql4() {
String hql = "select * from Grades limit ?0,?1 ";
Session currentSession = HibernateUtil.getCurrentSession();
Transaction transaction = currentSession.beginTransaction();
try {
NativeQuery query = currentSession.createSQLQuery(hql);
query.setParameter(0, 0);
query.setParameter(1, 2);
query.addEntity(Grades.class);
List<Grades> grades = query.list();
System.out.println(grades.toString());
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
}
transaction.commit();
}
}
网友评论