当前位置: 移动技术网 > IT编程>开发语言>Java > Hibernate

Hibernate

2020年07月14日  | 移动技术网IT编程  | 我要评论

持久化类的编写规则

什么是持久化类

  1. 持久化:将内存中的一个对象持久化到数据库中的过程.Hibernate就是用来进行持久化的框架
  2. 持久化类:一个Java对象与数据库的表建立了映射关系,那么这个类在Hibernate中称之为持久化类.(持久化类 = Java类 + 映射文件)

编写规则

1.对持久化类提供一个无参数的构造方法 — Hibernate需要使用凡是生成实例
2.属性需要私有,对私有属性提供get和set方法 — Hibernate中获取,设置对象的值
3. 对持久化类提供一个唯一标识OID与数据库主键对应 — Java中通过对象的地址区分是否同一个对象,数据库中通过主键确定是否是同一个记录,而在Hibernate中通过持久化类的OID的属性区分是否是同一个对象
4. 持久化类中属性尽量使用包装类 — 因为基本数据类型默认是0,包装类默认值是null (int => Integer,long=>Long,double=>Double)
5. 持久化类不能使用final进行修饰 — 延迟加载本身是Hibernate一个优化的手段,返回的是一个代理对象(Javassist),如果不能继承,不能产生代理对象,延迟加载也就会失败,load方法和get方法将会一样.

主键生成策略

主键的分类

  • 自然主键:主键的本身就是表中的一个字段(实体中的一个具体的属性)
  • 代理主键:主键的本身不是表中必须的一个字段(不是实体中的某个具体属性)
    在实际开发中,尽量使用代理主键
    1.一旦自然主键参与业务逻辑中,后期有可能需要修改源码
    2.好的程序设计满足OPC原则,对程序的扩展是open的,对修改源码是close的

主键生成策略

在映射文件中配置

<id name="cust_id" column="cust_id">
	<generator class="native"/>
</id>
  • increment : Hibernate中提供的自动增长机制,适用short、int、long类型的主键,在单线程中使用 .(首先发送一条语句select max(id) from stu,然后将查到的id + 1作为下一条记录的主键)
  • identity : 适用short、int、long类型的主键.使用的是数据库的自动增长机制.适用于有自动增长机制数据库(MySQL、MSSQL),但是Oracle没有自动增长
  • sequence : 适用short、int、long类型的主键.采用序列的方式.(Oracle支持序列).但MySQL不能使用sequence
  • uuid : 适用于字符串类型主键.使用Hibernate中的随即方式生成字符串主键
  • native : 本地策略,可以在identity和sequence之间进行自动切换
  • assigned : Hibernate放弃外键的管理,需要通过手动编写程序或者用户自己设置.
  • foreign : 外部的,一对一的一种关联映射的情况下使用(了解)

持久化类的三种状态

三种状态

  • 瞬时态 : 没有唯一的标识OID,没有被session管理
  • 持久态 : 有唯一的标识OID,被session管理
  • 托管态 : 有唯一的标识OID,不被session管理
public void demo1() {
		Session session = HibernateUtils.openSession();
		Transaction transaction = session.beginTransaction();
		Customer customer = new Customer(); //瞬时态 : 没有唯一的标识OID,没有被session管理
		customer.setCust_name("张三");
		Serializable id = session.save(customer);//持久态 : 有唯一的标识OID,被session管理
		transaction.commit();
		session.close();
		System.out.println(customer.getCust_name());//托管态 : 有唯一的标识OID,不被session管理
	}

站在三种状态角度看saveOrUpdate()方法

public void demo2() {
		Session session = HibernateUtils.openSession();
		Transaction transaction = session.beginTransaction();
		
		/*当为瞬时态对象时执行save方法*/
		/*Customer customer = new Customer(); 
		customer.setCust_name("张三");
		session.saveOrUpdate(customer);*/
		
		/*当为托管态对象时执行update方法*/
		Customer customer = new Customer(); 
		customer.setCust_id(3l);
		customer.setCust_name("李四");
		session.saveOrUpdate(customer);

		transaction.commit();
		session.close();
	}

持久态对象特性 : 持久态对象自动更新数据库

	public void demo3() {
		Session session = HibernateUtils.openSession();
		Transaction transaction = session.beginTransaction();
		Customer customer = session.get(Customer.class, 3l);
		customer.setCust_name("王五");
		//不用执行update方法,持久态对象自动更新数据库
		//session.update(customer);
		transaction.commit();
		session.close();
	}

一级缓存

什么是缓存

  • 缓存 : 是一种优化的方式,将数据存入到内存中,使用的时候直接从缓存中获取,不用通过向存储源获取

Hibernate的一级缓存

  • Hibernate框架中提供了优化手段 : 缓存、抓取策略.
  • Hibernate中提供了两种缓存机制:一级缓存、二级缓存
  • Hibernate的一级缓存:称为是session级别的缓存,一级缓存生命周期与session一致(一级缓存是由Session中的一系列Java集合构成的).一级缓存是自带的不可卸载的.
  • Hibernate的二级缓存:时SessionFactory级别的缓存,需要配置,一般不用Hibernate中的二级缓存,一般用redis等

证明一级缓存的存在

public void demo4() {
		Session session = HibernateUtils.openSession();
		Transaction transaction = session.beginTransaction();
		Customer customer1 = session.get(Customer.class, 1l);//发送SQL语句
		System.out.println(customer1);
		Customer customer2 = session.get(Customer.class, 1l);//不发送SQL语句
		System.out.println(customer2);
		transaction.commit();
		session.close();
	}

一级缓存的特殊区域 : 快照区
在这里插入图片描述

事务管理

什么是事务

  • 事务:是逻辑上的一组操作.组成这组操作的各个逻辑单元要么全部成功,要么全部失败.

事务特性

  • 原子性:代表事务不可分割
  • 一致性:代表事务执行的前后,数据的完整性保持一致
  • 隔离性:代表一个事务执行过程中,不应该受到其他事务的干扰
  • 持久性:代表事务执行完成后,数据就持久到数据库中

不考虑隔离性,引发的安全问题

  • 读问题:
    1.脏读 : 一个事务读到另一个事务未提交的数据(因为另一个事务可能会回滚)
    2.不可重复读 : 一个事务读到另一个事务已经提交的,但是update数据,导致在前一个事务多次查询结果不一致
    3.虚读 : 一个事务读到另一个事务已经提交的,但是insert数据,导致在前一个事务多次查询结果不一致
  • 写问题:
    引发两类丢失更新(了解)

读问题的解决

  • 设置事务的隔离级别
    1.Read uncommitted : 以上读问题都会发生
    2.Read committed : 解决脏读,但是不可重复读和虚读有可能发生(Oracle一般用)
    3.Repeatable read : 解决脏读和不可重复读,但是虚读有可能发生(MySQL一般用)

    4.Serializable : 解决所有问题(不允许事务并发)

在Hibernate核心文件hibernate.cfg.xml中配置

<!-- 
	事务隔离级别
		1 -> Read uncommitted 
		2 -> Read committed 
		4 -> Repeatable read 
		8 -> Serializable 
-->
<property name="hibernate.connection.isolation">4</property>

Hibernate的事务管理:线程绑定的session

在这里插入图片描述

  • 必须保证连接对象是同一个
    1.向下传递
    2.使用ThreadLocal对象(将这个连接绑定到当前线程中,在DAO的方法中通过当前的线程获得连接)
  • Hibernate框架内部已经绑定好了ThreadLoacl
    在SessionFactory中提供了一个方法getCurrentSession();
    这个方法默认不能用,需要配置才能用
public static Session getCurrentSession() {
		return sf.getCurrentSession();
	}

在核心文件hibernate.cfg.xml中配置

<!-- 配置当前线程绑定的Session -->
<property name="hibernate.current_session_context_class">thread</property>
  • thread : 与当前线程绑定
  • jta : 跨服务器绑定,例:实现向Oracle与MySQL的操作在同一个事务中
  • managed : - - -

其他常用API

Query***

  • query接口用于接收HQL,查询多个对象
    HQL:Hibernate Query Language,Hibernate查询语言(面向对象的查询语言)
@Test
	/*
	 * Query
	 */
	public void demo4() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		//简单查询
//		String hql = "from Customer";
//		Query query = session.createQuery(hql);
		//条件查询
//		String hql = "from Customer where cust_name like ?";
//		Query query = session.createQuery(hql);
//		query.setParameter(0, "王%");
		//分页查询
		String hql = "from Customer";
		Query query = session.createQuery(hql);
		query.setFirstResult(0);
		query.setMaxResults(3);
		List<Customer> list = query.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		tx.commit();
	}

Criteria***

  • Criteria : QBC ==> Query By Criteria
    更加面向对象的一个查询方式
@Test
	/*
	 * Criteria
	 */
	public void demo5() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		//简单查询
//		Criteria criteria = session.createCriteria(Customer.class);
		//条件查询
//		Criteria criteria = session.createCriteria(Customer.class);
//		criteria.add(Restrictions.like("cust_name", "张%"));
//		criteria.add(Restrictions.like("cust_name", "张",MatchMode.ANYWHERE));
		//分页查询
		Criteria criteria = session.createCriteria(Customer.class);
		criteria.setFirstResult(0);
		criteria.setMaxResults(3);
		List<Customer> list = criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		tx.commit();
	}

SQLQuery

  • SQLQuery用于接收SQL,特别复杂情况下使用SQL(例如关联八九个表)

本文地址:https://blog.csdn.net/a1669820631/article/details/107296075

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网