持久化,将内存中的一个对象持久化到数据库的过程。Hibernate框架就是用来进行持久化的框架。
持久化类,一个Java对象与数据库表建立了映射关系,那么这个类在Hibernate中称为持久化类。
持久化类=Java类+映射文件。
在实际开发中,尽量使用代理主键,因为一旦主键参与到业务逻辑中,后期可能需要修改原代码。好的程序设计满足OCP原则,对程序的扩展是Open的,对修改源码是close的。
在实际开发中,一般不允许用户手动设置主键,一般将主键交给数据库,或者手动编写程序进行设置。在Hibernate中为了减少程序编写,提供了很多主键生成策略。
Increment :hibernate中提供的自动增长机制,适用short,int,long类型党的主键,在单线程中使用。首先发送一条语句,select id from 表,然后让id+1作为下一条记录的主键。
Identity:自动增长,适用short,int,long类型的主键,使用的是数据库底层的自动增长,适用于有自动增长机制的数据库(MySQL,MSSQL),Oracle没有自动增长。
Sequence:自动增长,适用short,int,long类型的主键,采用序列方式(Oracle支持序列)。Mysql不能使用。
UUID:适用于字符串类型,使用Hibernate中的随机方式生成字符串主键。
Native:本地策略,可以在Identity和Sequence之间进行自动切换。
Assigned:hibernate放弃外键管理,需要通过手动编写程序或者自己设置。
Foreign:外部的,一对一的关联映射的情况下使用。(了解)
Hibernate是持久层框架,通过持久化类完成ORM操作,为了更好的管理持久化类,hIbernate把持久化类分层三种转态。
持久化类=Java类+映射
(1)瞬时态(Transient):没有唯一标识OID,没有被Session管理。
(2)持久态(Persistent):有唯一标识OID,被Session管理。
(持久化类的持久态对象,可以自动更新数据库)
(3)脱管态(Detached):有唯一标识OID,没有被Session管理。
@Test
// 三种状态区分
public void demo1() {
// 1通过工具类获取Session
Session session= HibernateUtils.openSession();
// 2开启事务
Transaction tx= session.beginTransaction();
// 3操作
// 向数据库插入一条记录
CustomerCustomer = new Customer(); // 1.瞬时态:没有位移标识OID(主键id),没有被session管理
Customer.setCust_name("小涵涵"); //
session.save(Customer);// 2.持久太:有唯一标识OID,被session管理
// 4事务提交 //
tx.commit(); //
// 5释放资源 //
session.close();//
System.out.println(Customer.getCust_name());// 3.托管态:有唯一标识OID,没有被session管理
}
(1)瞬时态:
获得:由new关键字创建
(2)持久态, 获得,通过Session的get()、load()方法或者Quey查询从数据库中获得.
(3)脱管态, 获得,脱管态无法获得,只能由其他状态转换而来。
@Test
/****
* 持久太的对象可以以自动更新数据库
*/
public void demo2() {
// 1通过工具类获取Session
Session session= HibernateUtils.openSession();
// 2开启事务
Transaction tx= session.beginTransaction();
// 3操作
/** 获取一个持久太对象了 **/
CustomerCustomer = (Customer) session.get(Customer.class, 1l);
Customer.setCust_name("王哈哈");
/** 此处可以省略一个update(如果此处数据和数据库一样,不执行Update()) **/
//session.update(Customer);
// 4事务提交
tx.commit();
// 5释放资源
session.close();
}
缓存是一种优化的方式,将一些数据放在内存,使用的时候直接从缓存中获取,不用通过数据源。
Hibernate一级缓存又称为“Session的缓存”。
Session内置不能被卸载,Session的缓存是事务范围的缓存(Session对象的生命周期通常对应一个数据库事务或者一个应用事务)。
一级缓存中,持久化类的每个实例都具有唯一的OID。
依赖于hibernate一级缓存【就是将数据库/硬盘文件中数据,放到缓存中(就是内存中一块空间),当再次使用时,可以直接从内存中获取数据信息】。
@Test
/****
* 证明一级缓存的存在
*/
public void demo3() {
// 1通过工具类获取Session
Session session= HibernateUtils.openSession();
// 2开启事务
Transaction tx= session.beginTransaction();
// 3操作
/**
* 分别用两次get执行两次查询id=1的客户,按道理执行两次get应发送两条sql语句,
* 且Customer1与Customer2不是同一个对象,
* 实际上只发送一次,且Customer1与Customer2是同一个对象
* 证明第二次查询使用的是一级缓存中的数据
**/
/** 数据库中第一本书的信息 **/
CustomerCustomer1 = (Customer) session.get(Customer.class, 1l);
System.out.println(Customer1);
/** 一级缓存中中第一本书的信息 **/
CustomerCustomer2 = (Customer) session.get(Customer.class, 1l);
System.out.println(Customer2);
System.out.println(Customer1==Customer2);
// 4事务提交
tx.commit();
// 5释放资源
session.close();
}
@Test
/****
* 深入了解持久态的对象可以以自动更新数据库
* 基于一级缓存:快照区
*/
public void demo4() {
// 1通过工具类获取Session
Session session= HibernateUtils.openSession();
// 2开启事务
Transaction tx= session.beginTransaction();
// 3操作
CustomerCustomer = (Customer) session.get(Customer.class, 1l);
/** 将信息存储于快照区 **/
Customer.setCust_name("张三丰");// 先将一级缓存区的【cust_name】修改为【"张三丰"】-----中间会进行一个比对查看是否一致,如果一致不更新(不会执行update语句),如果不一致----再将快照区中的【cust_name】修改为【"张三丰"】(执行update语句)。
// 4事务提交
tx.commit();
// 5释放资源
session.close();
}
事务:指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
1.原子性
(Atomic)(Atomicity)
事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。
2.一致性
(Consistent)(Consistency)
事务在完成时,必须使所有的数据都保持一致状态。
3.隔离性
(Insulation)(Isolation)
由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。
4.持久性
(Duration)(Durability)
事务完成之后,它对于系统的影响是永久性的。该修改即使出现致命的系统故障也将一直保持。
读的问题:
脏读:一个事务读到另一个事务未提交的数据。
不可重复读:一个事务读到另一个事务已经提交的update数据,导致在前一个事务多次查询结果不一致。
虚读:一个事务读到另一个事务已经提交的insert数据,导致在前一个事务多次查询结果不一致。
写问题(了解)
引发丢失更新。
设置事务的隔离级别
① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
② Repeatable read (可重复读):可避免脏读、不可重复读的发生。
③ Read committed (读已提交):可避免脏读的发生。
④ Read uncommitted (读未提交):最低级别,任何情况都无法保证。
在MySQL数据库中,支持上面四种隔离级别,默认的为Repeatable read (可重复读);而在Oracle数据库中,只支持Serializable(串行化)级别和Read committed (读已提交)这两种级别,其中默认的为Read committed级别。
核心配置文件中加入:
<!-- 事务隔离级别
0:TRANSACTION_NONE
1:TRANSACTION_READ_UNCOMMITTED
2:TRANSACTION_READ_COMMITTED
4:TRANSACTION_REPEATABLE_READ
8:TRANSACTION_SERIALIZABLE
-->
<property name="hibernate.connection.isolation">4</property>
改写工具类:
package top.yangxianyang.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* Hibernate的工具类
* @author yxy
*
*/
public class HibernateUtils {
public static finalConfiguration cfg;
public static finalSessionFactory sf;
static{
cfg = newConfiguration().configure();
sf = cfg.buildSessionFactory();
}
/*
* 提供获得session的方法
*/
public static SessionopenSession(){
return sf.openSession();
}
/*
* 提供获得session的方法
*/
public static SessiongetCurrentSession(){
return sf.getCurrentSession();
}
}
核心文件配置:
<!-- 配置当前线程绑定的Session -->
<property name="hibernate.current_session_context_class">thread</property>
代码:
package top.yangxianyang.demo1;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import top.yangxianyang.utils.HibernateUtils;
/*
* Hibernate线程绑定Session
* @author yxy
*
*/
public class HibernateTest3 {
@Test
public void demo1(){
Sessionsession=HibernateUtils.getCurrentSession();
Transactiontx=session.beginTransaction();
CustomerCustomer = new Customer();
Customer.setCust_name("涵涵");
session.save(Customer);
tx.commit();
}
}
1 使用query对象,不需要写sql语句,但是写hql语句
(1)hql:hibernate query language,hibernate提供查询语言,这个hql语句和普通sql语句很相似
(2)hql和sql语句区别:
- 使用sql操作表和表字段
- 使用hql操作实体类和属性
2 查询所有hql语句:
(1)from 实体类名称
3 Query对象使用
(1)创建Query对象
(2)调用query对象里面的方法得到结果
@Test
//Query
public void demo1(){
Sessionsession=HibernateUtils.getCurrentSession();
Transactiontx=session.beginTransaction();
//通过session获得Query接口
//String hql="fromCustomer";//简单查询
//条件查询
//String hql="fromCustomer where cust_name like ?";
//分页查询
String hql="fromCustomer";
Queryquery=session.createQuery(hql);
//设置条件
//query.setParameter(0,"张%");
//设置分页
query.setFirstResult(0);
query.setMaxResults(2);
List<Customer>list=query.list();
for (Customercustomer : list) {
System.out.println(customer);
}
tx.commit();
}
6.2Criteria
1使用这个对象时候,不需要写语句,直接调用方法实现,更加面向对象。
2 实现过程
(1)创建criteria对象
(2)调用对象里面的方法得到结果
@Test
//Criteria
public void demo2(){
Sessionsession=HibernateUtils.getCurrentSession();
Transactiontx=session.beginTransaction();
//通过session获得Criteria对象
Criteriact=session.createCriteria(Customer.class);
//条件查询
ct.add(Restrictions.like("cust_name","张%"));
List<Customer>list=ct.list();
//分页
ct.setFirstResult(0);
ct.setMaxResults(2);
for (Customercustomer : list) {
System.out.println(customer);
}
tx.commit();
}
6.3SQLQuery
1 使用hibernate时候,调用底层sql实现
2 实现过程
(1)创建对象
(2)调用对象的方法得到结果
@Test
// 查询所有
public void demo6(){
Session session= HibernateUtils.openSession();
Transaction tx= session.beginTransaction();
// 接收SQL:
SQLQuery query= session.createSQLQuery("select * from cst_customer");
List<Object[]>list = query.list();
for (Object[]objects : list) {
System.out.println(Arrays.toString(objects));
}
tx.commit();
session.close();
}
今天任务完成。
源码地址:
链接:https://pan.baidu.com/s/1rMQ9XBMIeu2O_VbNZBo3MQ密码:0hgz