持久化
将内存中的数据永久的存储到关系型数据库中
持久化类(元数据,映射)
一个Java类有了一个映射文件与数据库建立了关系,那么这个类就是持久化类
持久化类的编写规则
- 提供无参构造
- 类的属性需要私有,且提供共有的get和set方法
- 类的属性尽量使用包装类的类型
- 必须要有一个OID与表的主键对应
- 持久化类尽量不要使用final修饰
主键的分类
- 自然主键
把具有业务含义的字段作为主键(例如将身份证号作为主键) - 代理主键
不具备业务含义的字段
主键生成策略
- 适用于代理主键
increment:用于long,short或者int类型,有Hibernate自动以递增的方式生成唯一的标识符,每次增量为1
identity:采用数据库本身提供的主键生成标识符,条件是数据库支持自动增长数据类型
sequence:Hibernate根据底层数据库序列生成标识符,条件是数据库支持序列
native:自动从identity、sequence、hlio中挑选一种使用
uuid:采用128位的UUID算法来生成标识符 - 适用于自然主键
assigned:由Java程序负责生成标识符,如果不指定id元素的generator
属性,则默认使用该主键生成策略
持久化对象的三种状态
- 瞬时状态:不存在持久化标识OID,加入到了Session缓存中,且相关联的Session没有关闭,在数据库中有对应的记录。
- 持久状态:存在是持久化标识OID,加入到了Session缓存中,并且相关联的Session没有关闭,在数据库中有对应的记录。
- 脱管状态:存在持久化标识OID,并且仍然与数据库中的数据存在关联,只是失去了与当前session的关联。
持久化对象三种状态描述
- 当一个对象被执行 new 关键字后,该对象处于瞬时态;
- 当瞬时态对象执行Session的Save() 或 saveOrUpdate() 方法后,该对象被放入Session的一级缓存,对象进入持久态;
- 当持久态对象执行evict()、close()或clear()操作后,对象进入托管态;
- 当执行Session的get()、load()、find()或iterate()等方法从数据库查询对象时,查询到的对象也处于持久态;
- 当对数据库中的记录进行update()、saveOrUpdate()以及lock()等操作后,此时托管态的对象就过渡到持久态;
- 由于瞬时态和托管态的对象不在session的管理范围,所以会在一段时间后被JVM回收;
持久化对象三种状态的切换
瞬时态(由new关键字创建)转换到其他状态
瞬时态转换为持久态:执行Session的save()或saveOrUpdate()方法
瞬时态转换为托管态:为瞬时态对象设置持久化标识OID1
2Customer customer = new Customer(); //瞬时态
customer.setCust_id(1); //托管态持久态(通过Session中的get()、load(),或者Query查询从数据库中获得)转换到其他状态
持久态转换为瞬时态:执行Session的delete()方法
持久态转换为托管态:执行Session的evict()、close()、clear()方法。evict()用于清除一级缓存中的某一个对象,close()方法用于关闭Session,clear()方法用于清除一级缓存的所有对象。托管态(无法直接获得,由其他状态对象转换而来)转换到其他状态
托管态转换为持久态:执行Session的update()、saveOrUpdate
()或lock()方法
托管态转换为瞬时态:将托管态对象的持久化标识OID设置为null
持久态对象的特性
持久态对象能自动更新数据库
Hibernate一级缓存
Hibernate的缓存分为一级缓存和二级缓存,这两级缓存都位于持久化层。其中一层缓存为Hibernate内置缓存不能被卸载。一级缓存的作用就是减少对数据库的访问次数。
特点:
1)、当应用程序调用Session接口的save、update、saveOrUpdate方法时,如果Session缓存中没有相应的对象,Hibernate就会自动把从数据库查询到的相应对象信息加入到一级缓存中。
2)、当调用Session接口的load、get、以及Query接口的list、iterator方法时,会判断缓存中是否存在该对象,有则返回,不会查询数据库,如果没有,则取数据库中查询,并将其添加到一级缓存中。
3)、当调用Session的close方法时,Session将会被清空。
事务
事务的特性
- 原子性:(Atomic)要么全执行,要么全都不执行
- 一致性:(Consistency)事务完成时,所有的数据都保持一致
- 隔离性:(Isolation)一个事务不能被另一个事务干扰
- 持久性:(Durability)事务一旦提交,对数据库中的数据的改变就是永久性的
事务的并发问题
- 脏读:一个事务取到另一个事务未提交的数据
- 不可重复读:一个事务读到了另一个事务已经提交的update的数据,导致在同一个事务中的多次查询结果不一致
- 虚读/幻读:一个事务读到了另一个事务已经提交的insert的数据,导致在同一个事务中的多次查询结果不一致
事务的隔离级别
- 读未提交,一级
- 已提交读,二级
- 可重复读,四级
- 序列化/串行化,八级
事务的隔离级别由数据库提供,并不是所有的数据库都支持四种隔离级别。在使用数据库的时候,隔离级别越高,高全性越高,性能越低。
Hibernate中的事务管理
在Hibernate中使用事务1
2
3Transaction tx = session.beginTransaction(); //开启事务
tx.commit(); //提交
tx.rollback(); //回滚
在Hibernate中设置事务的隔离级别1
<property name="hibernate.connection.isolation">4</property>
Hibernate5中管理Session对象的三种方法
- Session对象的生命周期与本地线程绑定,thread
1
<property name="hibernate.current_session_content_class">thread</property>
Hibernate提供sessionFactory.getCurrentSession()创建一个session和ThreadLocal绑定
- Session对象的生命周期与JTA事务绑定,jta
- Hibernate委托程序管理Session对象的生命周期,managed
Query
HQL是Hibernate Query Language的缩写,语法很像SQL,但它完全面向对象。
使用步骤:
- 获得Hibernate的Session对象。
- 编写HQL
- 调用session.createQuery创建查询对象
- 如果HQL包含参数,则使用setXXX设置参数
- 调用Query对象的list()或uniqueResult()方法执行查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34简单示例
package me.yanrs.service;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import me.yanrs.domain.User;
import me.yanrs.utils.HibernateUtils;
public class HQL_Test {
public static void main(String[] args) {
hql_test();
}
public static void hql_test() {
Session session = HibernateUtils.openSession();
String hql = "from User where id=:id and name=:name";
Query query = session.createQuery(hql);
query.setInteger("id",1); //条件查询
query.setString("name", "test");
query.setFirstResult(0); //分页查询
query.setMaxResults(5);
List<User> list = query.list(); //list获取数据
String hql2 = "from User";
Query query2 = session.createQuery(hql2);
System.out.println(query2.uniqueResult());
System.out.println(list);
}
}
常用方法:setXXX、iterator、uniqueResult、executeUpdate、setFirstResult、setMaxResult
Criteria
又叫QBC(Query By Criteria)
使用步骤:
- 获得Hibernate的Session对象
- 通过Session获得Criteria对象
- 使用Restrictions的静态方法创建Criteria条件对象
- 使用Criteria对象中的add方法添加Criteria查询条件
- 执行Criteria的list()或者uniqueResult()获取结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33package me.yanrs.service;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import me.yanrs.domain.User;
import me.yanrs.utils.HibernateUtils;
public class HQL_Test {
public static void main(String[] args) {
//hql_test();
criteria_test();
}
public static void criteria_test() {
Session session = HibernateUtils.openSession();
Criteria createCriteria = session.createCriteria(User.class);
System.out.println(createCriteria.list()); //查询全部
createCriteria.add(Restrictions.eq("name", "test"));
System.out.println(createCriteria.list()); //条件查询
createCriteria.setFirstResult(0); //分页查询
createCriteria.setMaxResults(5);
System.out.println(createCriteria.list());
System.out.println(createCriteria.uniqueResult());//获取查询的结果条数
}
}
SQLQuery
接收SQL语句进行查询1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37简单示例
package me.yanrs.service;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import me.yanrs.domain.User;
import me.yanrs.utils.HibernateUtils;
public class HQL_Test {
public static void main(String[] args) {
//hql_test();
//criteria_test();
sqlquery_test();
}
public static void sqlquery_test() {
//基本查询
String sql = "select * from user";
Session session = HibernateUtils.openSession();
SQLQuery query = session.createSQLQuery(sql);
System.out.println(query.list());
//封装到对象中
String sql1 = "select * from user";
Session session1 = HibernateUtils.openSession();
SQLQuery query1 = session.createSQLQuery(sql1);
query1.addEntity(User.class);
System.out.println(query1.list());
}
}