持久化:将内存中的对象持久化到数据库中的过程就是持久化。Hibernate 就是用来进行持久化的框架。html
持久化类:一个 Java 对象与数据库的表创建了映射关系,那么这个类在 Hibernate 中称为是持久化类。java
一、对持久化类提供一个无参构造方法。sql
二、属性须要私有,对私有属性提供 public 的 get 和 set 方法。数据库
三、对持久化类提供一个惟一标识 OID 与数据库表主键对应。数组
Java 中经过对象的地址区分是不是同一个对象,数据库中经过主键区分是不是同一条记录,而在 Hibernate 中是经过持久化类的 OID 属性区分是不是同一个对象。缓存
四、持久化类中属性尽可能使用包装类类型。session
五、持久化类不要用 final 修饰。框架
Hibernate 是持久层的框架,经过持久化类完成 ORM 操做。为了更好的管理,Hibernate 将持久化类对象分为了三种状态。ide
没有惟一标识 OID,且没有被 session 管理。工具
有惟一标示 OID,且没有被 session 管理。
有惟一标识 OID,且被 session 管理。
Session session1 = HibernateUtil.openSession(); Transaction transaction1 = session1.beginTransaction(); Customer customer = new Customer(); // 瞬时态:无惟一标识,未被 session1 管理。 customer.setCust_id(1L); // 未被 session1 管理,若是数据库数据有与之对应的惟一标示(即数据库表中有一行 cust_id=1 的数据),则为游离态,不然依旧是瞬时态。 customer.setCust_name("李四"); session1.saveOrUpdate(customer); // 交由 session1 管理,且数据库数据有对应惟一标示的数据,转为持久态。 transaction1.commit(); session1.close(); Session session2 = HibernateUtil.openSession(); Transaction transaction2 = session2.beginTransaction(); System.out.println(customer); // 以前托管到的 session1 已关闭,即未被 session1 也未被 session2 管理,但有与数据库数据对应的惟一标识,此时为游离态。 session2.delete(customer); // session2 主动放弃管理,且从数据库中删除与惟一标示对应的记录,转为瞬时态。 transaction2.commit(); session2.close(); /* 总结: 瞬时态对象 得到: Customer customer = new Customer(); 状态转换: ->持久态: session.save(customer); 、 session.saveOrUpdate(customer); ->游离态: customer.setCust_id(1L); 游离态对象 得到: Customer customer = new Customer();customer.setCust_id(1L); 状态转换: ->持久态 session.update(customer); 、 session.saveOrUpdate(customer); ->瞬时态: customer.setCust_id(null); 持久态对象 得到: session.get(Customer.class,1L); 、 session.load(Customer.class,1L); 状态转换: ->瞬时态: session.delete(customer); ->游离态: session.close(); 、 session.clear(); 、 session1.evict(customer); */
主键自己就是表中有意义的字段。
主键自己不是表中必须的字段。
一旦天然主键参与到业务逻辑中,后期就有可能修改源代码。
好的程序设计知足 OCP 原则,对程序的扩展是 open 的,对修改源码是 close 的。
hibernate 提供的自动增加机制,使用 short 、int 、long 类型的主键,在单线程程序中使用。
适用 short 、int 、long 类型的主键,使用的是数据库底层的自增机制,适用于有自增机制的数据库(MySQL、MSSQL)。
适用 short 、int 、long 类型的主键,采用的是序列的方式,适用于支持序列机制的数据库(Oracle)。
适用于字符串类型主键,由 Hibernate 随机生成字符串主键。
本地策略,能够在 identity 和 sequence 间自动切换。
Hibernate 放弃主键的管理,经过手动编码给主键赋值。
依赖外部主键,适用于一对一关联映射状况下使用。
一种优化的方式,将数据放入内存中,使用的时候直接从内存中取,不用经过存储源。
Hibernate 提供了两种缓存机制:一级缓存、二级缓存。
是 Session 级别的缓存,一级缓存生命周期与 Session 一致,由 Session 中一系列 Java 集合构成,自带不可卸载。
Hibernate 的一级缓存就是指 Session 缓存,Session 缓存是一块内存空间,用来存放管理的持久化类对象,在使用 Hibernate 查询对象时,首先会使用对象属性的惟一标示 OID 值在一级缓存中进行查找,若是找到匹配的 OID 值的对象,就直接将该对象从一级缓存中取出使用,不会再查询数据库;若是没有找到相同 OID 值的对象,则会去数据库中查找相应数据。当从数据库中查询到所需数据时,该数据信息也会放置到一级缓存中。
在 Session 接口的实现中包含一系列 Java 集合,这些 Java 集合构成了 Session 缓存。只要 Session 实例未结束生命周期,存放在它缓存中的持久化类对象也不会结束生命周期。因此一级缓存也被称为 Session 级别的缓存。
Session session = HibernateUtil.openSession(); Customer customer1 = session.get(Customer.class, 1L);// 发出 select 的 SQL 语句 Customer customer2 = session.get(Customer.class, 1L);// 无 SQL 发出,只是取出上一行查询出的放到一级缓存的 customer1 赋值给 customer2 System.out.println(customer1 == customer2);// true :即 customer1 和 customer2 是同一个对象 session.close();
Session session = HibernateUtil.openSession(); Transaction transaction = session.beginTransaction(); Customer customer1 = new Customer(); customer1.setCust_name("郭德纲"); Serializable id = session.save(customer1); // 在事务提交时发出 insert 的 SQL 语句,且将保存的对象放入一份到一级缓存中 Customer customer2 = session.get(Customer.class, id); // 无 SQL 语句发出,只是取上一行新增时保存到一级缓存中的 customer1 赋值给 customer2 System.out.println(customer1 == customer2);// true :即 customer1 和 customer2 是同一个对象 transaction.commit(); session.close();
Session session = HibernateUtil.openSession(); Transaction transaction = session.beginTransaction(); Customer customer1 = new Customer(); customer1.setCust_id(1L); customer1.setCust_name("郭德纲"); session.update(customer1); // 在事务提交时发出 update 的 SQL 语句,且将要更新的对象放入一份到一级缓存中 Customer customer2 = session.get(Customer.class, 1L); // 无 SQL 语句发出,只是取上一行更新时保存到一级缓存中的 customer1 赋值给 customer2 System.out.println(customer1 == customer2);// true :即 customer1 和 customer2 是同一个对象 transaction.commit(); session.close();
当 Hibernate 将持久化类对象放入一级缓存时,并不只仅只是放入一份,还拷贝了一份放入了一级缓存中的一个特殊区域-快照区。而 Hibernate 利用这个快照区实现了持久化类对象的一个特性,看以下示例:
Session session = HibernateUtil.openSession(); Customer customer = session.get(Customer.class, 1L); Transaction transaction = session.beginTransaction(); customer.setCust_name("郭德纲"); // session.update(customer); // 即使省略这个更新操做,在事务提交时 Hibernate 仍然会发出更新的 SQL 语句。 transaction.commit(); session.close();
当咱们使持久化类对象的属性发生改变时,一级缓存中对应的持久化对象也会随之发生改变,而快照区对应的持久化对象不变。而当事务提交时,Hibernate 会对比一级缓存中存放的持久化类对象和它对应快照中存放的持久化类对象。若是有差别,Hibernate 则帮咱们执行更新操做;若是没有差别,则不会对数据库进行操做。
在核心配置文件 hibernate.cfg.xml 中添加以下属性便可:
<!-- 配置事务隔离级别,有以下四个值: 1 :读未提交 (Read uncommitted) 2 :读已提交 (Read committed) 4 :可重复读 (Repeatable read) 默认级别 8 :串行化 (Serializable) --> <property name="hibernate.connection.isolation">4</property>
在核心配置文件 hibernate.cfg.xml 中添加以下属性:
<!-- thread : Session 对象的生命周期与本地线程绑定。 jta : Session 对象的生命周期与 JTA 事务绑定。 managed : Hibernate 委托程序来管理 Session 对象的生命周期。 --> <property name="hibernate.current_session_context_class">thread</property>
而后就能够保证在当前线程中经过 org.hibernate.SessionFactory.getCurrentSession 方法获取到的 Session 是同一个实例。抽取工具类:
package com.zze.util; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtil { public static final Configuration cfg; public static final SessionFactory sf; static { cfg = new Configuration().configure(); sf = cfg.buildSessionFactory(); } public static Session openSession() { return sf.openSession(); } public static Session getCurrentSession() { return sf.getCurrentSession(); } }
HQL (Hibernate Query Language) ,相对 sql 来讲,sql 中的表名在 hql 中用类名替代,sql 中的列名在 hql 中用属性名替代。
Session currentSession = HibernateUtil.getCurrentSession(); Transaction transaction = currentSession.beginTransaction(); String hql = "from Customer"; // 简单查询 Query query = currentSession.createQuery(hql); List<Customer> customerList = query.list(); for (Customer customer : customerList) { System.out.println(customer); } transaction.commit();
Session currentSession = HibernateUtil.getCurrentSession(); Transaction transaction = currentSession.beginTransaction(); String hql = "from Customer where cust_name like ?"; Query query = currentSession.createQuery(hql); query.setParameter(0, "张%"); List<Customer> customerList = query.list(); for (Customer customer : customerList) { System.out.println(customer); } transaction.commit();
Session currentSession = HibernateUtil.getCurrentSession(); Transaction transaction = currentSession.beginTransaction(); String hql = "from Customer"; Query query = currentSession.createQuery(hql); query.setFirstResult(2); // 起始索引,从 0 开始 query.setMaxResults(2); // 每页条数 List<Customer> customerList = query.list(); for (Customer customer : customerList) { System.out.println(customer); } transaction.commit();
QBC (Query By Criteria) API 提供了检索对象的另外一种方式,它主要由 Criteria 接口、Criterion 接口和 Expresson 类组成,它支持在运行时动态生成查询语句,是一种更面向对象的查询方式。
Session currentSession = HibernateUtil.getCurrentSession(); Transaction transaction = currentSession.beginTransaction(); Criteria criteria = currentSession.createCriteria(Customer.class); List<Customer> customerList = criteria.list(); for (Customer customer : customerList) { System.out.println(customer); } transaction.commit();
Session currentSession = HibernateUtil.getCurrentSession(); Transaction transaction = currentSession.beginTransaction(); Criteria criteria = currentSession.createCriteria(Customer.class); criteria.add(Restrictions.like("cust_name", "张", MatchMode.END)); List<Customer> customerList = criteria.list(); for (Customer customer : customerList) { System.out.println(customer); } transaction.commit();
Session currentSession = HibernateUtil.getCurrentSession(); Transaction transaction = currentSession.beginTransaction(); Criteria criteria = currentSession.createCriteria(Customer.class); criteria.setFirstResult(2); criteria.setMaxResults(2); List<Customer> customerList = criteria.list(); for (Customer customer : customerList) { System.out.println(customer); } transaction.commit();
Hibernate 也支持咱们使用原生 SQL 查询。
Session currentSession = HibernateUtil.getCurrentSession(); Transaction transaction = currentSession.beginTransaction(); SQLQuery sqlQuery = currentSession.createSQLQuery("select * from customer"); // 默认返回一个 Object 数组对象的列表,数组的每一项对应数据库中每一行数据的一列 List<Object[]> customerList = sqlQuery.list(); for (Object[] customer : customerList) { System.out.println(String.format("id:%s,cust_name:%s", customer[0], customer[1])); } transaction.commit();
Session session = HibernateUtil.getCurrentSession(); session.beginTransaction(); String sql = "select * from customer where cust_name like ?"; SQLQuery sqlQuery = session.createSQLQuery(sql); sqlQuery.addEntity(Customer.class); sqlQuery.setParameter(0,"张%"); List<Customer> customerList = sqlQuery.list(); for (Customer customer : customerList) { System.out.println(customer); } session.getTransaction().commit();
Session session = HibernateUtil.getCurrentSession(); session.beginTransaction(); String sql = "select cust_id id,cust_name name from customer"; SQLQuery sqlQuery = session.createSQLQuery(sql); sqlQuery.addScalar("id", new LongType()); sqlQuery.addScalar("name"); sqlQuery.setResultTransformer(Transformers.aliasToBean(Customer2.class)); List<Customer2> userList = (List<Customer2>)sqlQuery.list(); for (Customer2 customer2 : userList) { System.out.println(customer2); } session.getTransaction().commit();