本章重点讲述Hibernate对象的三种状态以及如何配置二级缓存

有关Hibernate的三种状态如何相互转换网上都能查到,官方文档描述的也比较详细。这里主要是针对几个重点方法做代码演示。

一、状态转换

package learnhow;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test; import util.HibernateUtil;
import model.example.User; public class HibernateTest {
private Session session;
private Transaction transaction; @Test
public void testSaveOrUpdate() {
session = HibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
// Transient状态:session缓存和数据库中都没有
User user = new User();
user.setUserName("Linda");
session.save(user);
// Persistent状态:save()方法以后,对象获得id并且在session中保留有引用
user = (User) session.get(User.class, 1);
transaction.commit();
session.close();
// Detached状态:session被关闭,数据库和内存中有对象
user.setUserName("John");
session = HibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
// Persistent状态:此时如果使用save()方法,Hibernate会抛出异常,使用update()方法可以更新数据库数据
session.update(user);
// Transient状态:数据库和session缓存中都删除对象,此时对象有id值,但依然属于T状态
session.delete(user);
transaction.commit();
session.close();
user.setUserName("Bob");
// Transient状态:有id值的T对象为了防止冲突,应该把id值重置
user.setId(0);
session = HibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
// Persistent状态:重新将对象持久化
session.saveOrUpdate(user);
transaction.commit();
session.close();
}
}

HibernateTest.java

以上代码Hibernate会依次执行插入-更新-删除-插入。

二、延迟加载

package learnhow;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test; import util.HibernateUtil;
import model.example.User; public class HibernateTest {
private Session session;
private Transaction transaction; @Test
public void testGetAndLoad() {
session = HibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
// 立即发出sql语句查询结果
User user1 = (User) session.get(User.class, 2);
transaction.commit();
session.close();
session = HibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
// 仅返回代理对象,在实际使用的时候才会触发查询条件
User user2 = (User) session.load(User.class, 2);
transaction.commit();
session.close();
// 关闭session以后可以正常使用
System.out.println(user1);
// 关闭session以后查询对象会抛出异常:org.hibernate.LazyInitializationException: could
// not initialize proxy - no Session
System.out.println(user2);
}
}

HibernateTest.java

延迟加载异常是使用Hibernate之中经常遇到的问题。例如,如果在级联条件下设置了fetch = FetchType.LAZY,关闭session以后试图触发查询操作也会抛出异常。

以上代码在4.x和5.x版本中均运行正常,唯一的不同点是在5.x版本中通过get()等方法获取对象的时候不需要强制转型。

三、配置二级缓存

Hibernate通过org.hibernate.testing.cache.CachingRegionFactory对象实现对二级缓存的管理,但是在官方文档中明确注明只适合于测试环境。因此,如果需要在生产环境中使用Hibernate配置二级缓存,官方推荐EHCache。

(1)首先通过Maven引入依赖关系(最后一项依赖是针对二级缓存的,前面都是之前两章用到的包)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.learnhow</groupId>
<artifactId>Hibernate_Demo</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Hibernate_Demo Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<!-- 引入新版依赖 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.0.6.Final</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.13</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.20.0-GA</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- Hibernate官方推荐的数据库连接池是c3p0 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>5.0.6.Final</version>
</dependency>
<!-- 添加二级缓存的实现依赖 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>5.0.6.Final</version>
</dependency>
</dependencies>
<build>
<finalName>Hibernate5_Demo</finalName>
</build>
</project>

pom.xml

(2)从Hibernate官方文档里找一份ehcache.xml文件,复制到项目的resources目录下

<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
-->
<ehcache> <!-- Sets the path to the directory where cache .data files are created. If the path is a Java System Property it is replaced by
its value in the running VM. The following properties are translated:
user.home - User's home directory
user.dir - User's current working directory
java.io.tmpdir - Default temp file path -->
<diskStore path="./target/tmp"/> <!--Default Cache configuration. These will applied to caches programmatically created through
the CacheManager. The following attributes are required for defaultCache: maxInMemory - Sets the maximum number of objects that will be created in memory
eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element
is never expired.
timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
if the element is not eternal. Idle time is now - last accessed time
timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
if the element is not eternal. TTL is now - creation time
overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache
has reached the maxInMemory limit. -->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/> <!--Predefined caches. Add your cache configuration settings here.
If you do not have a configuration for your cache a WARNING will be issued when the
CacheManager starts The following attributes are required for defaultCache: name - Sets the name of the cache. This is used to identify the cache. It must be unique.
maxInMemory - Sets the maximum number of objects that will be created in memory
eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element
is never expired.
timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
if the element is not eternal. Idle time is now - last accessed time
timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
if the element is not eternal. TTL is now - creation time
overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache
has reached the maxInMemory limit. --> <!-- Sample cache named sampleCache1
This cache contains a maximum in memory of 10000 elements, and will expire
an element if it is idle for more than 5 minutes and lives for more than
10 minutes. If there are more than 10000 elements it will overflow to the
disk cache, which in this configuration will go to wherever java.io.tmp is
defined on your system. On a standard Linux system this will be /tmp"
-->
<cache name="sampleCache1"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/> <!-- Sample cache named sampleCache2
This cache contains 1000 elements. Elements will always be held in memory.
They are not expired. -->
<cache name="sampleCache2"
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/> --> <!-- Place configuration for your caches following --> </ehcache>

ehcache.xml

(3)配置了二级缓存之后还可以继续配置查询缓存

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration>
<session-factory>
<!-- 数据库连接配置 -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/learnhow</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- JDBC连接池,开发环境设置1就可以了 -->
<property name="connection.pool_size">1</property>
<!-- 数据库方言 -->
<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<!-- session交给hibernate管理 -->
<property name="current_session_context_class">thread</property>
<!-- 是否显示sql语句 -->
<property name="show_sql">true</property>
<!-- 是否对语句格式化输出 -->
<property name="hbm2ddl.auto">update</property>
<!-- 是否对语句格式化输出 -->
<property name="format_sql">true</property>
<!-- 配置二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<!-- 配置查询缓存,查询缓存需要依赖二级缓存 -->
<property name="hibernate.cache.use_query_cache">true</property> </session-factory>
</hibernate-configuration>

hibernate.cfg.xml

(4)另外还需要在model对象上添加@Cache注解

package model.example;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id; import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy; @Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User {
private int id;
private String userName; @Id
@GeneratedValue
public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getUserName() {
return userName;
} public void setUserName(String userName) {
this.userName = userName;
} }

User.java

最后使用Junit测试效果:

package learnhow;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test; import model.example.User;
import util.HibernateUtil; public class HibernateTest {
private Session session;
private Transaction transaction; @Test
public void testSecondLevelCache() {
session = HibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
User user1 = session.get(User.class, 1);
transaction.commit();
session.close();
session = HibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
// 配置二级缓存以后查询同一个对象只发送一条查询语句
User user2 = session.get(User.class, 1);
transaction.commit();
session.close();
} @Test
public void testQueryCache() {
session = HibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
String hql = "FROM User";
// 配置了查询缓存以后,第一次查询将结果集保存进缓存中
List<User> users_1 = session.createQuery(hql).setCacheable(true).list();
for (User u : users_1) {
System.out.println(u.getUserName());
}
transaction.commit();
session.close();
session = HibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
// 第二次查询直接通过缓存获得结果集
List<User> users_2 = session.createQuery(hql).setCacheable(true).list();
for (User u : users_2) {
System.out.println(u.getUserName());
}
transaction.commit();
session.close();
}
}

HibernateTest.java

如果以上测试方法都只触发一条查询语句就代表配置生效了。

(有关Hibernate的基础配置,我能想到的大概就这些,要继续深入学习就得读源码了~呼,好累)

Hibernate 基础配置及常用功能(三)的更多相关文章

  1. Hibernate 基础配置及常用功能(一)

    本来是想等全部框架测试完以后再统一发布的,但是随着测试的一点点增加感觉把需要叙述的东西放在一起终将会是一场灾难.所以还是打算分成几章来描述,其中还包括一些有待解决的问题.短期很难腾出时间来仔细阅读Hi ...

  2. Hibernate 基础配置及常用功能(二)

    本章主要是描述几种经典映射关系,顺带比较Hibernate4.x和Hibernate5.x之间的区别. 一.建立测试工程目录 有关实体类之间的相互映射关系,Hibernate官方文档其实描述的非常详细 ...

  3. Hibernate学习笔记2.1(Hibernate基础配置)

    Hibernate基础配置 1.<property name="hbm2ddl.auto">update</property> 在SessionFactor ...

  4. Fedora 28 系统基础配置以及常用软件安装方式

    实验说明: 很多人说Linux很难用,很难上手,其实不然,倘若不玩游戏,其实很多发行版Linux都可以成为主力系统,就比如本章要讲的 Fedora 28.本章会从镜像来源.系统安装.基础配置和常用软件 ...

  5. JAVA基础语法:常用功能符以及循环结构和分支结构(转载)

    3.JAVA基础语法:常用功能符以及循环结构和分支结构 1.常用功能符 注释 ("文字"是被注释的部分) //文字 单行注释 /文字/ 多行注释 算术运算符 + - * / / 整 ...

  6. Ansible基础配置与常用模块使用

    环境介绍: Ansible服务端IP:192.168.2.215 Ansible客户端IP:192.168.2.216.192.168.2.218.192.168.2.113   一.创建Ansibl ...

  7. hibernate基础配置

    数据库表名和类名 一致 注解:可写可不写: XML:可写可不写: <class name="Student"> 不一致 注解:  public class Teache ...

  8. 3.Hibernate基础配置

    1.Hibernate.cfg.xml:hbm2ddl.auto 在SessionFactory创建时,自动检查数据库结构,或者将数据库schema的DDL导出到数据库 <property na ...

  9. Hibernate学习笔记2.3(Hibernate基础配置)

    映射,注释可以放在成员变量上面,也可以放在get方法上面 写在成员变量的话 破坏了java的面向对象思维 直接让hibernate访问内部的私有元素 要是能直接设指不合适哈哈 所以主张写在get方法上 ...

随机推荐

  1. 【iCore3 双核心板_FPGA】实验二十八:基于SDRAM 的VGA 驱动器的设计

    本实验设计的VGA显示驱动完全基于FPGA实现,用SDRAM做缓存设备,通过ARM控制VGA显示的内容.ARM 通过FSMC总线向FPGA发送数据,由于总线的速度和VGA的显示速度与SDRAM的读写速 ...

  2. 10个jQuery小技巧

    收集的10个 jQuery 小技巧/代码片段,可以帮你快速开发. 1.返回顶部按钮 你可以利用 animate 和 scrollTop 来实现返回顶部的动画,而不需要使用其他插件. $('a.top' ...

  3. Thinking in Java——笔记(14)

    Type Information The need for RTTI Because it is a dynamically bound method, the proper behavior wil ...

  4. Vim,极简使用教程,让你瞬间脱离键鼠切换的痛苦

    注:看大家对Vim仇恨极大,其实它只是一种文本操作方式,可以减少键鼠的切换,从而让编辑文本的操作更迅捷.并不等同于IDE,在我看来,它们是两个是包含关系,IDE可以有Vim编辑模式.Vim或许可以通过 ...

  5. <把时间当做朋友>读书笔记

    这本书我早就看过,还想再来一遍 开始这一行动是看李萌在朋友圈晒101计划,每天健身,读书半小时之类的,我也想做点啥,那就每天睡前读书半小时吧,怎么坚持下去呢? 我不想晒到朋友圈里,那就晒给玉玉看吧, ...

  6. Windows下wnmp相关配置

    #wnmp mysqld -install net start mysql memcached -d uninstall memcached -d install net start memcache ...

  7. tensorfolw配置过程中遇到的一些问题及其解决过程的记录(配置SqueezeDet: Unified, Small, Low Power Fully Convolutional Neural Networks for Real-Time Object Detection for Autonomous Driving)

    今天看到一篇关于检测的论文<SqueezeDet: Unified, Small, Low Power Fully Convolutional Neural Networks for Real- ...

  8. Glide请求图片能携带Cookie的哟!

    在Web编程中我们都很熟知一个概念,当有了seesion登录状态时,你可以访问一些资源但如果你没有登录的话很多资源是无法访问的. 在android的WebApi中当然一样拥有这个概念.比如,用户的头像 ...

  9. easyui 分页 MVC

    View <script type="text/javascript"> var dd; var grid; $(function () { var queryData ...

  10. php 入门1

    一.php在引入文件和js引入文件的区别 1.php在引入文件是用代码控制,而js是通过标签的属性src引入: 2.php引入可以在引入下写代码,而js是不可以的 3.静态效果的js可以引入的时间,引 ...