1、初始Hibernate

1.1 理解ORM原理

目前面向对象思想是软件开发的基本思想,关系数据库又是应用系统中必不可少的一环,但是面向对象是从软件工程的基本原则发展而来,而关系数据库确是从数学理论的基础诞生的,两者的区别是巨大的,为了解决这个问题,ORM便应运而生。

ORM(Object Relational Mapping)是对象到关系的映射,它的作用是在关系数据库和对象之间做一个自动映射,将数据库中数据表映射成为对象,也就是持久化类,对关系型数据以对象的形式进行操作,减少应用开发过程中数据持久化的编程任务。可以把ORM理解成关系型数据和对象的一个纽带,开发人员只需关注纽带的一端映射的对象即可。ORM原理如下图示。

1.2 Hibernate简介

作为一个优秀的持久层框架,Hibernate充分体现了ORM的设计理念,提供了高效的对象到关系型数据库的持久化服务,它将持久化服务从软件业务层中完全抽取出来,让业务逻辑的处理更加简单,程序之间的各种业务并非紧密耦合,更加有利于高效地开发与维护。使开发人员在程序中可以利用面向对象的思想对关系型数据进行持久化操作,为关系型数据库和对象型数据打造了一个便捷的高速公路。下图就是一个简单的Hibernate体系概要图。

从这个概要图可以清楚地看出,Hibernate是通过数据库和配置信息进行数据持久化服务和持久化对象的。Hibernate封装了数据库的访问细节,通过配置的属性文件这条纽带连接着关系型数据库和程序中的实体类。

在Hibernate中有非常重要的3个类,它们分别是配置类(Configuration)、会话工厂类(SessionFactory)和会话类(Session)。

说明
配置类(Configuration) 配置类主要负责管理Hibernate的配置信息以及启动Hibernate,在Hibernate运行时配置类会读取一些底层实现的基本信息,其中包括数据库的URL,数据库用户名、数据库密码、数据库驱动类和数据库适配器(dialect)。
会话工厂类(SessionFactory) 会话工厂类是生成Session的工厂,它保存了当前数据库中所有的映射关系,可能只有一个可选的二级数据缓存,并且它是线程安全的。但是会话工厂类是一个重量级对象,它的初始化创建过程会消耗大量的系统资源。
会话类(Session) 会话类是Hibernate中数据库持久化操作的核心,它将负责Hibernate所有的持久化操作,通过它开发人员可以实现数据库基本的增、删、改、差的操作。但会话类并不是线程安全的,应注意不要多个线程共享一个Session。

2、Hibernate入门

2.1 获取Hibernate

从Hibernate的官方网站获取所需的jar包,官方网址为http://www.hibernate.org,在该网站可以免费获取Hibernate的帮助文档和jar包。解压下载后的Hibernate文件,将目录:hibernate-release-5.4.4.Final\lib\required 下的所有jar包文件添加到项目中。

注意:除了需要下载Hibernate的jar包,还需要下载JDBC数据库驱动并添加到项目中。

了解搭建Hibernate开发环境的详细说明,请浏览本博客的文章:Hibernate搭建开发环境

2.2 Hibernate配置文件

Hibernate通过读取默认的XML配置文件hibernate.cfg.xml加载数据库的配置信息,该配置文件被默认放于项目的classpath根目录下(src目录下)。

【示例】连接应用的MySQL数据库,XML文件的配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"><hibernate-configuration><session-factory><!-- 数据库驱动 --><property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property><!-- 数据库连接的URL --><property name="connection.url">jdbc:mysql://localhost:3306/db_admin?useSSL=false&amp;serverTimezone=GMT%2b8</property><!-- 数据库连接用户名 --><property name="connection.username">root</property><!-- 数据库连接密码 --><property name="connection.password">123456</property><!-- Hibernate方言 --><property name="dialect">org.hibernate.dialect.MySQL5Dialect</property><!-- 打印SQL语句 --><property name="show_sql">true</property><!-- 映射文件  --><mapping resource="com/pjb/entity/User.hbm.xml"/></session-factory></hibernate-configuration>

从配置文件中可以看出配置的信息包括整个数据库的信息,例如数据库的驱动、URL地址、用户名、密码和Hibernate使用的方言,还需要管理程序中各个数据库表的映射文件。配置文件中<property>元素的常用配置属性如下表所示。

<property>元素的常用配置属性:

属性 说明
connection.driver_class 连接数据库的驱动。
connection.url 连接的数据库的URL地址。
connection.username 连接数据库用户名。
connection.password 连接数据库密码。
dialect 设置连接数据库使用的方言。
show_sql 是否在控制台打印SQL语句。
format_sql 是否格式化SQL语句。
hbm2ddl.auto 是否自动生成数据库表。

在程序开发的过程中,一般会将show_sql属性设置为true,以便在控制台打印自动生成的SQL语句,方便程序调试。

以上只是Hibernate配置的一部分,还可以配置表的自动生成、Hibernate的数据连接池等。

2.3 了解并编写持久化类

Hibernate中持久化类是Hibernate操作的对象,也就是通过对象-关系映射(ORM)后数据库表所映射的实体类,用来描述数据库表的结构信息。在持久化类中的属性应该与数据库表中的字段相匹配。

【示例】创建名称为User的JavaBean。

package com.pjb.entity;/*** 用户信息实体类* @author pan_junbiao**/
public class User
{private int id;        //用户编号private String name;   //用户姓名private String blog;   //博客地址private int age;       //年龄private String remark; //备注//默认的构造方法public User() {}public int getId(){return id;}public void setId(int id){this.id = id;}public String getName(){return name;}public void setName(String name){this.name = name;}public String getBlog(){return blog;}public void setBlog(String blog){this.blog = blog;}public int getAge(){return age;}public void setAge(int age){this.age = age;}public String getRemark(){return remark;}public void setRemark(String remark){this.remark = remark;}
}

User类作为一个简单的持久化类,它符合最基本的JavaBean编码规范,也就是POJO(Plain Old Java Object)编程模型。持久化类中的每个属性都有相应的setXXX()和getXXX()方法,它不依赖于任何接口和继承任何类。

Hibernate中的持久化类有4条编程规则:

(1)实现一个默认的构造函数

所有的持久化类中都必须含有一个默认的无参数构造方法(User类中就含有无参数的构造方法),以便Hibernate通过Constructor.newInstance()实例化持久化类。

(2)提供一个标识属性(可选)

标识属性一般映射的是数据库表中的主键字段,例如User中的属性id,建议在持久化类中添加一致的标识属性。

(3)使用非final类(可选)

如果使用了final类,Hibernate就不能使用代理来延迟关联加载,这会影响开发人员进行性能优化的选择。

(4)为属性声明访问器(可选)

持久化类的属性不能声明为public的,最好以private的setXXX()和getXXX()方法对属性进行持久化。

2.4 Hibernate映射

Hibernate的核心就是对象关系映射,对象和关系型数据库之间的映射通常是用XML文档来实现的。这个映射文档被设计成易读的,并且可以手工修改。映射文件的命名规则为*.hbm.xml,以User的持久化类的映射文件为例,代码如下:对User对象进行配置。

【示例】创建文件名为User.hbm.xml的配置文件,对User对象进行配置。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 用户信息字段配置信息 -->
<hibernate-mapping><class name="com.pjb.entity.User" table="tb_user"><!-- 用户编号id值 --><id name="id" column="id" type="int"><!-- 持久化类的唯一性标识 --><generator class="native"/></id><!-- 用户姓名 --><property name="name" type="string" not-null="true" length="20"><column name="name"/></property><!-- 博客地址 --><property name="blog" type="string" not-null="true" length="20"><column name="blog"/></property><!-- 年龄 --><property name="age" type="int"><column name="age"/></property><!-- 备注 --><property name="remark" type="string" length="50"><column name="remark"/></property></class>
</hibernate-mapping>

<DOCTYPE>元素:

在所有的Hibernate映射文件中都需要定义如上所示的<DOCTYPE>元素,用来获取DTD文件。

<hibernate-mapping>元素:

<hibernate-mapping>元素是映射文件中其他元素的根元素,这个元素中包含一些可选属性,例如,schema属性是指该文件映射表所在数据库的schema名称;package属性是指定一个包前缀,如果在<class>元素中没有指定全限的类,就将使用package属性定义的包前缀作为包名。

<class>元素:

<class>元素主要用于指定持久化类和映射的数据库表名。name属性需要指定持久化类的全限定的类名(如:com.pjb.entity.User);table属性就是持久化类所映射的数据库表名。

<class>元素中包含了一个<id>属性和多个<property>元素,<id>属性用于持久化类的唯一标识与数据库表的主键字段的映射,在<id>属性中通过<generator>元素定义主键的生成策略。<property>元素用于持久化类的其他属性和数据库表中非主键字段的映射。

持久化类映射文件<property>元素的常用配置属性:

属性名称 说明
name 持久化类属性的名称,以小写字母开头。
column 数据库字段名。
type 数据库的字段类型。
length 数据库字段定义的长度。
not-null 该数据库字段是否可以为空,该属性为布尔变量。
unique 该数据库字段是否唯一,该属性为布尔变量。
lazy 是否延迟抓取,该属性为布尔变量。

注意:如果在映射文件中没有配置column和type属性,Hibernate将会默认使用持久化类中的属性名称和属性类型匹配数据表中的字段。

2.5 Hibernate主键策略

<id>元素的子元素<generator>元素是一个Java类的名字,用来为持久化类的实例生成唯一的标识映射数据库中的主键字段。在配置文件中通过设置<generator>元素的属性设置Hibernate的主键生成策略,主要的内置属性如下表所示。

属 性 名 称 说明
increment 用于为long、short、或者int类型生成唯一标识。在集群下不要使用该属性。
identity 由底层数据库生成主键,前提是底层数据库支持自增字段类型。
sequence 根据底层数据库的序列生成主键,前提是底层数据库支持序列。
hilo 根据高/低算法生成,把特定表的字段作为高位值来源,在默认的情况下选用hibernate_unique_key表的next_hi字段。
native 根据底层数据库对自动生成标识符的支持能力选择identity、sequence或hilo。
assigned 由程序负责主键的生成,此时持久化类的唯一标识不能声明为private类型。
select 通过数据库触发器生成主键。
foreign 使用另一个相关联的对象的标识符,通常和<one-to-one>一起使用。

3、Hibernate数据持久化

持久化操作是Hibernate的核心,下面将介绍如何创建线程安全的Hibernate初始化类,并利用Hibernate的Session对象实现基本的数据库增、删、改、查的操作。

3.1 Hibernate实例状态

Hibernate的实例状态分为三种,分别为瞬时状态(Transient)、持久化状态(Persistent)、脱管状态(Detached)。

瞬时状态(Transient):

实体对象是通过Java中的new关键字开辟内存空间创建的Java对象,但是它并没有纳入Hibernate的Session的管理中,如果没有变量对它引用,它将被JVM(垃圾回收器)回收。瞬时状态的对象在内存中是孤立存在的,它与数据库中的数据无任何关联,仅是一个信息携带的载体。

假如一个瞬时状态对象被持久化状态对象引用,它也会自动变为持久化状态对象。

持久化状态(Persistent):

持久化状态对象存在于数据库中的数据关系,它总是与会话状态(Session)和事务(Transaction)关联在一起。当持久化状态对象发送改动时并不会立即执行数据库操作。只有当事务结束时,才会更新数据库,以便保证Hibernate的持久化对象和数据库操作的同步性。当持久化状态对象变为托管状态对象时,它将不再Hibernate持久层的管理范围之内。

脱管状态(Detached):

当持久化状态的对象的Session关闭之后,这个对象就从持久化状态的对象变为脱管状态的对象。脱管状态的对象仍然存在与数据库中的数据关联,只是它并不在Hibernate的Session管理范围之内。如果将脱管状态的对象重新关联某个新的Session上,它将变回持久化状态对象。

Hibernate中3种实例状态的关系如图:

3.2 Hibernate初始化类

Session对象是Hibernate中数据库持久化操作的核心,它将负责Hibernate所有的持久化操作,通过它开发人员可以实现数据库基本的增、删、改、查的操作。而Session对象又是通过SessionFactory对象获取的,那么SessionFactory对象又是如何创建的呢?可以通过Configuration对象创建SessionFactory,关键代码如下:

Configuration cfg = new Configuration().configure(); // 加载Hibernate配置文件
factory = cfg.buildSessionFactory();                 // 实例化SessionFactory

Configuration对象会加载Hibernate的基本配置信息,如果没有在configure()方法中指定加载配置XML文档的路径信息,Configuration对象会默认加载项目classpath根目录(src目录)下的hibernate.cfg.xml文件。

【示例】创建HibernateUtil类,用于实例化对Hibernate的初始化。

package com.pjb.hibernate;import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;/*** Hibernate公共类* @author pan_junbiao**/
public class HibernateUtil {private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();//ThreadLocal对象private static SessionFactory sessionFactory = null;//SessionFactory对象//静态块static {try {// 加载Hibernate配置文件Configuration cfg = new Configuration().configure();sessionFactory = cfg.buildSessionFactory();} catch (Exception e) {System.err.println("创建会话工厂失败");e.printStackTrace();}}/***   获取Session*  @return Session*  @throws HibernateException*/public static Session getSession() throws HibernateException {Session session = (Session) threadLocal.get();if (session == null || !session.isOpen()) {if (sessionFactory == null) {rebuildSessionFactory();}session = (sessionFactory != null) ? sessionFactory.openSession(): null;threadLocal.set(session);}return session;}/*** 重建会话工厂*/public static void rebuildSessionFactory() {try {// 加载Hibernate配置文件Configuration cfg = new Configuration().configure();sessionFactory = cfg.buildSessionFactory();} catch (Exception e) {System.err.println("创建会话工厂失败");e.printStackTrace();}}/*** 获取SessionFactory对象* @return SessionFactory对象*/public static SessionFactory getSessionFactory() {return sessionFactory;}/** * 关闭Session*  @throws HibernateException*/public static void closeSession() throws HibernateException {Session session = (Session) threadLocal.get();threadLocal.set(null);if (session != null) {session.close();//关闭Session}}
}

通过这个Hibernate公共类,就可以有效地管理Session,避免了Session的多线程共享数据的问题。

3.3 保存数据

Hibernate对JDBC的操作进行了轻量级的封装,使开发人员可以利用Session对象以面向对象的思想实现对关系型数据库的操作,轻而易举地实现数据库最基本的增、删、改、查操作。

Hibernate数据持久化流程图:

【示例】新增用户信息。

(1)在MySQL数据库中创建tb_user用户信息表。

-- 判断数据表是否存在,存在则删除
DROP TABLE IF EXISTS tb_user;-- 创建“用户信息”数据表
CREATE TABLE IF NOT EXISTS tb_user
( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '用户编号',NAME VARCHAR(20) NOT NULL COMMENT '用户姓名',blog VARCHAR(50) NOT NULL COMMENT '博客地址',age INT COMMENT '年龄',remark VARCHAR(50) COMMENT '备注'
) COMMENT = '用户信息表';

(2)创建新增用户类AddUser.java。

package com.pjb.main;import org.hibernate.Session;
import org.hibernate.Transaction;
import com.pjb.hibernate.HibernateUtil;
import com.pjb.entity.User;/*** 新增用户信息* @author pan_junbiao**/
public class AddUser
{public static void main(String[] args){Session session = null;   //声明Session对象Transaction ts = null;    //声明事务对象User user = new User();   //实例化持久化类//为持久化类属性赋值user.setName("pan_junbiao的博客");user.setBlog("https://blog.csdn.net/pan_junbiao");user.setAge(32);user.setRemark("您好,欢迎访问 pan_junbiao的博客!");try{session = HibernateUtil.getSession(); //获取Session对象ts = session.beginTransaction(); //开启事务session.save(user); //执行数据库添加操作ts.commit(); //事务提交System.out.println("数据添加成功");}catch(Exception ex){//事务回滚if(ts!=null){ts.rollback();}System.out.println("数据添加失败");ex.printStackTrace();}finally{HibernateUtil.closeSession();  //关闭Session对象}}
}

程序运行后,在数据库tb_user表查询信息:

说明:持久化对象User在创建之后是瞬时状态,在Session执行save()方法之后持久化对象User的状态变为持久化状态,但是这时数据操作并未提交给数据库,在事务执行commit()方法之后,才完成数据库的操作,此时的持久化对象User成为脏(dirty)对象。Session关闭之后,持久化对象User的状态变为托管状态,并最后被JVM回收。

3.4 查询数据

Session对象提供了种对象装载的方法,分别是get()方法和load()方法。

3.4.1 get()方法

如果开发人员不确定数据库中是否有匹配的记录存在,就可以使用get()方法进行对象封装,因为它会立刻访问数据库。如果数据库中没有匹配记录存在,会返回null。

【示例】使用get()方法获取User对象。

package com.pjb.main;import org.hibernate.Session;
import com.pjb.hibernate.HibernateUtil;
import com.pjb.entity.User;/*** 获取用户信息* @author pan_junbiao**/
public class GetUser
{public static void main(String[] args){Session session = null;     //声明Session对象try {//Hibernate的持久化操作session = HibernateUtil.getSession();//获取SessionUser user = (User) session.get(User.class, 1); //装载对象System.out.println("用户编号:"+user.getId());System.out.println("用户姓名:"+user.getName());System.out.println("博客地址:"+user.getBlog());System.out.println("年龄:"+user.getAge());System.out.println("备注:"+user.getRemark());} catch (Exception e) {System.out.println("对象装载失败");e.printStackTrace();} finally{HibernateUtil.closeSession();//关闭Session}}
}

说明:get()方法中包含两个参数:一个是持久化对象,另一个是持久化对象中的唯一标识。get()方法的返回值可能为null,也可能是一个持久化对象。

3.4.2 load()方法

load()方法返回对象的代理,只有在返回对象被调用时,Hibernate才会发出SQL语句去查询对象。

【示例】使用load()方法获取User对象。

package com.pjb.main;import org.hibernate.Session;
import com.pjb.hibernate.HibernateUtil;
import com.pjb.entity.User;/*** 获取用户信息* @author pan_junbiao**/
public class GetUser
{public static void main(String[] args){Session session = null;     //声明Session对象try {//Hibernate的持久化操作session = HibernateUtil.getSession();//获取SessionUser user = (User) session.load(User.class, 1); //装载对象System.out.println("用户编号:"+user.getId());System.out.println("用户姓名:"+user.getName());System.out.println("博客地址:"+user.getBlog());System.out.println("年龄:"+user.getAge());System.out.println("备注:"+user.getRemark());} catch (Exception e) {System.out.println("对象装载失败");e.printStackTrace();} finally{HibernateUtil.closeSession();//关闭Session}}
}

另外,load()方法还可以加载到指定的对象实例上。

session = HibernateUtil.getSession(); //获取Session
User user = new User();               //实例化对象
session.load(user,1);                 //装载对象

两种方法的执行结果:

(1)get()方法执行结果。

(2)load()方法执行结果。

说明:由于load()方法返回对象在被调用时Hibernate才会发出SQL语句去查询对象,所以在用户编号信息输出之后才输出SQL语句。因为用户编号在程序中是已知的,并不需要查询。

3.5 删除数据

在Session对象中需要使用delete()方法进行数据的删除操作。但是只有对象在持久化状态时才能进行执行delete()方法,所以在删除数据之前,首先需要将对象的状态转换为持久化状态。

【示例】使用delete()方法删除指定的用户信息。

package com.pjb.main;import com.pjb.entity.User;
import com.pjb.hibernate.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;/*** 删除用户信息* @author pan_junbiao**/
public class DeleteUser
{public static void main(String[] args){Session session = null;     //声明Session对象Transaction ts = null;   //声明事务对象try {session = HibernateUtil.getSession(); //获取SessionUser user = (User) session.get(User.class, 2); //装载对象if(user!=null){ts = session.beginTransaction(); //开启事务session.delete(user); //删除持久化对象ts.commit(); //事务提交System.out.println("删除成功");}else{System.out.println("用户不存在");}} catch (Exception e) {//事务回滚if(ts!=null){ts.rollback();}System.out.println("删除失败");e.printStackTrace();} finally{HibernateUtil.closeSession();//关闭Session}}
}

执行结果:

3.6 修改数据

在Hibernate的Session的管理中,如果程序对持久化状态的对象做出了修改,当Session刷出时Hibernate会对实例进行持久化操作,利用Hibernate的该特性就可以实现商品信息的修改操作。

 【示例】修改用户信息。

package com.pjb.main;import org.hibernate.Session;
import org.hibernate.Transaction;
import com.pjb.entity.User;
import com.pjb.hibernate.HibernateUtil;/*** 修改用户信息* @author pan_junbiao**/
public class UpdateUser
{public static void main(String[] args){Session session = null;     //声明Session对象Transaction ts = null;   //声明事务对象try {session = HibernateUtil.getSession(); //获取SessionUser user = (User) session.get(User.class, 1); //装载对象if(user!=null){user.setName("pan_junbiao的博客_002");user.setRemark("您好,欢迎访问 pan_junbiao的博客_002!");ts = session.beginTransaction(); //开启事务session.update(user); //删除持久化对象ts.commit(); //事务提交System.out.println("修改成功");}else{System.out.println("用户不存在");}} catch (Exception e) {//事务回滚if(ts!=null){ts.rollback();}System.out.println("修改失败");e.printStackTrace();} finally{HibernateUtil.closeSession();//关闭Session}}
}

执行结果:

程序运行后,在数据库tb_user表查询信息:

3.7 关于延迟加载

在load()方法的讲解中,其实已经涉及了延迟加载的策略。在使用load()方法加载持久化对象时,它返回的是一个未初始化的代理(代理无须从数据库中抓取数据对象的数据),直到调用代理的某个方法时Hibernate才会访问数据库。在非延迟加载过程中,Hibernate会直接访问数据库,并不会使用代理对象。

当装载的对象长时间没有调用的时候,就会被垃圾回收器所回收,在程序中合理地使用延迟加载策略将会优化系统的性能。采用延迟加载可以使Hibernate节省系统的内存空间,否则每加载一个持久化对象就需要将其关联的数据信息装载到内存中,这将为系统节约部分不必要的开销。

在Hibernate中可以通过使用一些采用延迟加载策略封装的方法实现延迟加载的功能,如load()方法,同时还可以通过设置映射文件中的<property>元素中的lazy属性实现该功能。

【示例】以用户信息的XML文档配置为例,实现延迟加载设置。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 用户信息字段配置信息 -->
<hibernate-mapping><class name="com.pjb.entity.User" table="tb_user"><!-- 用户编号id值 --><id name="id" column="id" type="int"><!-- 持久化类的唯一性标识 --><generator class="native"/></id><!-- 用户姓名 --><property name="name" type="string" not-null="true" length="20" lazy="true"><column name="name"/></property></class>
</hibernate-mapping>

通过该方式的设置,用户名称属性就被设置成了延迟加载。

4、使用Hibernate缓存

缓存是数据库数据在内存中的临时容器,是数据库与应用程序的中间件。

在Hibernate中也采用了缓存的技术,使Hibernate可以更加高效地进行数据持久化操作。Hibernate数据缓存分为两种,分别为一级缓存(Session Level,也称为内部缓存)和二级缓存(SessionFactory Level)。

4.1 一级缓存的使用

Hibernate的一级缓存属于Session级缓存,所以它的生命周期与Session是相同的,它随Session的创建而创建,随Session的销毁而销毁。

当程序使用Session加载持久化对象时,Session首先会根据加载的数据类和唯一性标识在缓存中查找是否存在此对象的缓存实例,如果存在将其作为结果返回,否则Session会继续向二级缓存中查找实例对象。

注意:在Hibernate中不同的Session之间是不能共享一级缓存的,也就是说,一个Session不能访问其他Session在一级缓存中的对象缓存示例。

【示例】在同一Session中查询两次用户信息。

package com.pjb.main;import org.hibernate.Session;
import com.pjb.hibernate.HibernateUtil;
import com.pjb.entity.User;/*** 获取用户信息* @author pan_junbiao**/
public class GetUser
{public static void main(String[] args){Session session = null;     //声明Session对象try {//Hibernate的持久化操作session = HibernateUtil.getSession();//获取SessionUser user1 = (User) session.get(User.class, 1); //第一次装载对象System.out.println("第一次装载对象");User user2 = (User) session.get(User.class, 1); //第二次装载对象System.out.println("第二次装载对象");} catch (Exception e) {e.printStackTrace();} finally{HibernateUtil.closeSession();//关闭Session}}
}

执行结果:

从控制台输出的信息中可以看出,Hibernate只访问了一次数据库,第二次对象加载时是从一级缓存中将该对象的缓存实例以结果的形式直接返回。

4.2 二级缓存的介绍

Hibernate的二级缓存将由从属于一个SessionFactory的所有Session对象共享。当程序使用Session加载持久化对象时,Session首先会根据加载的数据类和唯一性标识在缓存中查找是否存在此对象的缓存实例,如果存在将其作为结果返回,否则Session会继续向二级缓存中查找实例对象,如果二级缓存中也无匹配对象,Hibernate将直接访问数据库。

由于Hibernate本身并未提供二级缓存的产品化实现,所以需要引入第三方插件实现二级缓存的策略。例如使用EHCache作为Hibernate默认的二级缓存。

Hibernate技术相关推荐

  1. Hibernate 技术(二)

    Hibernate一级缓存 简介 缓存,介于应用程序和永久数据存储源之间,作用是为了降低应用程序对物理数据源访问的频率,从而提高应用的运行性能. 例如我们cpu执行效率每秒处理的数据高达上千兆,而我们 ...

  2. myeclipse java可视化_使用MyEclipse可视化开发Hibernate实例

    使用MyEclipse可视化开发Hibernate实例 2.7节的例子源代码在配套光盘sourcecode/workspace目录的chapter02_first项目中. 这个实例主要演示如何使用My ...

  3. java web 应用技术与案例教程_《Java Web应用开发技术与案例教程》怎么样_目录_pdf在线阅读 - 课课家教育...

    出版说明 前言 第1章 java Web应用开发技术概述 1.1 Java Web应用开发技术简介 1.1.1 Java Web应用 1.1.2 Java Web应用开发技术 1.2 Java Web ...

  4. hibernate映射数据库表如何在不插入值的情况下使表中字段默认值生效

    问题描述:    hibernate技术中对应数据库中每一个表,都会有一个映射文件与之对应,此文件描述数据库表中每一个字段的类型.长度.是否可空等属性.在进行表中记录的插入(更新)操作时,hibern ...

  5. hibernate理解

    SSH框架: Struts框架, 基于mvc模式的应用层框架技术! Hibernate,基于持久层的框架(数据访问层使用)! Spring,创建对象处理对象的依赖关系以及框架整合! Dao代码,如何编 ...

  6. Sass系统技术选型笔记(2)JBPM

    jbpm从4开始有了两个分支(烦死了,大家就不能统一下么)activiti和jbpm,目前二者都升级到了6,这两个版本的差别和底层技术的差别网上都很清楚了,下面又进入了选择题时间: jbpm6的好处是 ...

  7. java毕业设计——基于java+J2EE+Hibernate的校园二手交易网站设计与实现(毕业论文+程序源码)——二手交易网站

    基于java+J2EE+Hibernate的校园二手交易网站设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+J2EE+Hibernate的校园二手交易网站设计与实现,文章末尾附有 ...

  8. 爱的乐章,Hibernate之三部曲

    爱的乐章,Hibernate之三部曲 摘要 本文介绍了笔者使用Hibernate的三个阶段.第一个阶段完全被Hibernate的优点吸引.第二个阶段发现Hibernate在性能上的一些缺陷.笔者通过实 ...

  9. 6个的IT技术开发网站

    http://www.iteye.com ItEye是一个软件开发人员的深度交流社区.JavaEye创建于2003年9月9日,2011年4月1日更名为Iteye,ItEye一直致力于为中国的软件开发人 ...

  10. mysql智能停车场,智能停车场管理系统设计与实现(Hibernate和Struts,MySQL)

    智能停车场管理系统设计与实现(Hibernate和Struts,MySQL)(论文11800字,程序代码,MySQL数据库) 摘要:本论文旨在设计一款停车管理系统.本系统基于J2EE标准,采用B/S架 ...

最新文章

  1. javascript中的闭包这一篇就够了
  2. centos 7 yum安装mysql完整过程记录
  3. Python语言程序设计基础(2)—— Python程序实例解析
  4. 【Arthas】Arthas 类查找和反编译原理
  5. Springboot项目中static文件和templates文件的区别
  6. Django下载、安装
  7. Java 弱密码校验判断处理
  8. 保险场景化与场景即保险——新保险
  9. .Net 文件名后缀的详细解释
  10. Java+spring+springmvc 基于ssm的交通事故档案管理系统#毕业设计
  11. Conventional-path insert(传统路径插入)
  12. 《Java-第十一章》之图书管理系统
  13. 2022年无线蓝牙耳机排行榜,音质好性价比高的无线蓝牙耳机品牌推荐
  14. Django框架之美多商城项目
  15. 解决 torchtext 无法下载 glove
  16. 计算机毕业设计Java-ssm博弈论学习网站源码+系统+数据库+lw文档
  17. 解决java前台传递时间到后台相差8个小时的时区问题
  18. 新概念英语(第四册,新版)学习(原文及全文翻译)——Lesson 10 - Silicon Valley(硅谷)
  19. 可视化:python绘制多组多维数据雷达图
  20. 航空飞机线束检测—ATA-1000系列线束测试仪

热门文章

  1. LinuxCentOS 7镜像下载
  2. 智能制造-汽车行业线体工艺模拟仿真应用
  3. JavaScript成语消消乐
  4. STM32F103 驱动DS18B20
  5. Java JSP技术详解:(一)JSP 简介
  6. 基于遗传算法车辆路径问题(VRP)
  7. Laravel 获取文件并保存
  8. QQ音乐播放地址 API
  9. 计算机的毕设课题,计算机毕设课题大全.pdf
  10. 快速对二叉树和前中后序遍历的相互转化