Java第三阶段之Hibernate4查询方式、高级配置

十Hibernate 查询方式

1.Hibernate 查询方式简介

1,导航对象图查询方式;
2,OID 查询方式;
3,本地 SQL 查询方式;
4,HQL 查询方式;
5,QBC 查询方式;(QueryByCriteria)

2.本地 SQL 查询方式

3.HQL 查询方式

HQL(HibernateQueryLanguage)是面向对象的查询语言;是使用最广的一种查询方式;
1,普通查询;
2,带条件查询;
3,使用别名;
4,对结果排序;
5,分页查询;
6,查询单个对象;
7,链式写法;

新建项目Hibernate10
->model层。Student.java

package com.java1234.model;

public class Student {

	private int id;
	private String name;
	private int age;
	
	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 int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
	}	
}

->添加三条记录
->Student.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.java1234.model">

	<class name="Student" table="t_student">
		<id name="id" column="stuId">
			<generator class="native"></generator>
		</id>
		
		<property name="name" column="stuName"></property>
		<property name="age" column="stuAge"></property>
	</class>

</hibernate-mapping>

->新建service层,StudentTest.java

package com.java1234.service;


import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.java1234.model.Student;
import com.java1234.util.HibernateUtil;

public class StudentTest {

	private SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
	private Session session;
	
	@Before
	public void setUp() throws Exception {
		session=sessionFactory.openSession(); // 生成一个session
	    session.beginTransaction(); // 开启事务
	}

	@After
	public void tearDown() throws Exception {
		 session.getTransaction().commit(); // 提交事务
		 session.close(); // 关闭session
	}

	@Test
	public void testSQLQuery() {//查询所有的学生
		String sql="select * from t_student";
		Query query=session.createSQLQuery(sql).addEntity(Student.class);
		List studentList=query.list();
		Iterator it=studentList.iterator();
		while(it.hasNext()){
			Student s=(Student)it.next();
			System.out.println(s);
		}		
	}
	//运行结果:Hibernate:select * from t_student
	//Student[id=1,name=张三,age=10]
	//Student[id=2,name=李四,age=15]
	//Student[id=3,name=王五,age=13]
	
	@Test
	public void testSQLQuery2() {//怎么带参数,要模糊查询姓张的10岁的同学
		String sql="select * from t_student where stuName like :stuName and stuAge=:stuAge";
		Query query=session.createSQLQuery(sql).addEntity(Student.class);
		query.setString("stuName", "张%");
		query.setInteger("stuAge", 10);
		List studentList=query.list();
		Iterator it=studentList.iterator();
		while(it.hasNext()){
			Student s=(Student)it.next();
			System.out.println(s);
		}		
	}
	
	@Test
	public void testHQLQuery() {//
		String hql="from Student";
		Query query=session.createQuery(hql);
		List<Student> studentList=(List<Student>)query.list();//可以用泛型
		Iterator it=studentList.iterator();
		while(it.hasNext()){
			Student s=(Student)it.next();
			System.out.println(s);
		}		
	}
	//Hibernate:select student0_.stuId as stuId1_0_,student0_.stuName as
    //Student[id=1,name=张三,age=10]
	//Student[id=2,name=李四,age=15]
	//Student[id=3,name=王五,age=13]
	
	@Test
	public void testHQLQuery2() {//带条件的查询
		String hql="from Student where name like :stuName and age=:stuAge";//属性是类里面的属性哦
		Query query=session.createQuery(hql);
		query.setString("stuName", "张%");
		query.setInteger("stuAge", 10);
		List<Student> studentList=(List<Student>)query.list();
		Iterator it=studentList.iterator();
		while(it.hasNext()){
			Student s=(Student)it.next();
			System.out.println(s);
		}		
	}
	
	@Test
	public void testHQLQuery3() {//使用别名
		String hql="from Student as s where s.name like :stuName and s.age=:stuAge";
		Query query=session.createQuery(hql);
		query.setString("stuName", "张%");
		query.setInteger("stuAge", 10);
		List<Student> studentList=(List<Student>)query.list();
		Iterator it=studentList.iterator();
		while(it.hasNext()){
			Student s=(Student)it.next();
			System.out.println(s);
		}		
	}
	
	@Test
	public void testHQLQuery4() {//对结果排序,默认的是id从小到大升序。这里我们按照年龄降序
		String hql="from Student order by age desc";
		Query query=session.createQuery(hql);
		List<Student> studentList=(List<Student>)query.list();
		Iterator it=studentList.iterator();
		while(it.hasNext()){
			Student s=(Student)it.next();
			System.out.println(s);
		}		
	}
	//Hibernate:select student0_.stuId as stuId1_0_,student0_stuName as
	//Student[id=2,name=李四,age=15]
	//Student[id=3,name=王五,age=13]
	//Student[id=1,name=张三,age=10]
	
	@Test
	public void testHQLQuery5() {//分页,是使用接口的
		String hql="from Student";
		Query query=session.createQuery(hql);
		query.setFirstResult(1);从谁开始取。从0的话,就是从第一条开始取起。
		query.setMaxResults(2);取几个
		List<Student> studentList=(List<Student>)query.list();
		Iterator it=studentList.iterator();
		while(it.hasNext()){
			Student s=(Student)it.next();
			System.out.println(s);
		}		
	}
	//Hibernate:select student0_.stuId as stuId1_0_,student0_.stuName
	//Student[id=2,name=李四,age=15]
	//Student[id=3,name=王五,age=10]
	
	@Test
	public void testHQLQuery6() {//查询单个对象。还是使用接口
		String hql="from Student";
		Query query=session.createQuery(hql);
		query.setFirstResult(1);
		query.setMaxResults(1);
		Student student=(Student)query.uniqueResult();//就是一条记录,使用unique
		System.out.println(student);	
	}
	
	
	@Test
	public void testHQLQuery7() {//链式写法
		String hql="from Student as s where s.name like :stuName and s.age=:stuAge";
		Query query=session.createQuery(hql);
		List<Student> studentList=(List<Student>)query
				.setString("stuName", "张%")
				.setInteger("stuAge", 10)
				.list();//不停的追加
		Iterator it=studentList.iterator();
		while(it.hasNext()){
			Student s=(Student)it.next();
			System.out.println(s);
		}		
	}
}

4.QBC 查询方式(QueryByCriteria)

QBC 查询方式(QueryByCriteria)是用一套接口来实现的查询方式;
1,普通查询;
2,带条件查询;
3,对结果排序;
4,分页查询;
5,查询单个对象;
6,链式写法;

@Test
	public void testQBCQuery1(){
		Criteria criteria=session.createCriteria(Student.class);
		List<Student> studentList=criteria.list();
		Iterator it=studentList.iterator();
		while(it.hasNext()){
			Student s=(Student)it.next();
			System.out.println(s);
		}	
	}
	//Hibernate:select this.stuId as stuId1_0_0_,this.stuName
	//Student[id=1,name=张三,age=10]
	//Student[id=2,name=李四,age=10]
	//Student[id=3,name=王五,age=10]
	
	@Test
	public void testQBCQuery2(){//带条件的
		Criteria criteria=session.createCriteria(Student.class);
		Criterion c1=Restrictions.like("name", "张%");
		Criterion c2=Restrictions.eq("age", 10);
		criteria.add(c1);
		criteria.add(c2);
		List<Student> studentList=criteria.list();
		Iterator it=studentList.iterator();
		while(it.hasNext()){
			Student s=(Student)it.next();
			System.out.println(s);
		}	
	}
	
	@Test
	public void testQBCQuery3(){//通过年龄降序查询
		Criteria criteria=session.createCriteria(Student.class);
		criteria.addOrder(Order.desc("age"));
		List<Student> studentList=criteria.list();
		Iterator it=studentList.iterator();
		while(it.hasNext()){
			Student s=(Student)it.next();
			System.out.println(s);
		}	
	}
	
	@Test
	public void testQBCQuery4(){//分页
		Criteria criteria=session.createCriteria(Student.class);
		criteria.setFirstResult(2);
		criteria.setMaxResults(2);
		List<Student> studentList=criteria.list();
		Iterator it=studentList.iterator();
		while(it.hasNext()){
			Student s=(Student)it.next();
			System.out.println(s);
		}	
	}
	
	@Test
	public void testQBCQuery5(){//查询单个对象
		Criteria criteria=session.createCriteria(Student.class);
		criteria.setFirstResult(2);
		criteria.setMaxResults(1);
		Student student=(Student)criteria.uniqueResult();
		System.out.println(student);
	}
	
	
	@Test
	public void testQBCQuery6(){//链式查询
		Criteria criteria=session.createCriteria(Student.class);
		List<Student> studentList=criteria
				.setFirstResult(0)
				.setMaxResults(2)//和分页的代码比对着看
				.list();
		Iterator it=studentList.iterator();
		while(it.hasNext()){
			Student s=(Student)it.next();
			System.out.println(s);
		}	
	}

十一Hibernate 高级配置

1.配置数据库连接池

反问数据库,需要不断的创建和释放连接,假如访问量大的话,效率比较低级,服务器消耗大; 使用数据库连接池,我们可以根据实际项目的情况,定义连接池的连接个数,从而可以实现从连接池获取连接,用户放回到连接池。从而有效的提高的系统的执行效率; Hibernate 自带的连接池不是很好,有 bug; 推荐使用 C3P0,proxool 等;
新建项目Hibernate11
->新建文件夹C3P0
导入jar包,optional->c3p0里面的三个包
c3p0-0.9.2.1
hibernate-c3p0-4.3.5.Final
mchange-commons-java-0.2.3.4
官方给了两种配置
在这里插入图片描述
在这里插入图片描述
->hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>

<hibernate-configuration>

    <session-factory>

        <!--数据库连接设置 -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property>
        <property name="connection.username">root</property>
        <property name="connection.password">123456</property>

       
        <!-- 方言 -->
        <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
	
        <!-- 控制台显示SQL -->
        <property name="show_sql">true</property>

        <!-- 自动更新表结构 -->
        <property name="hbm2ddl.auto">update</property>
        
        **<!-- 最小连接数 --> 
 		<property name="c3p0.min_size">7</property> 
 		<!-- 最大连接数 -->   
 		<property name="c3p0.max_size">42</property> 
 		<!-- 获得连接的超时时间,如果超过这个时间,会抛出异常,单位毫秒 -->  
 		<property name="c3p0.timeout">1800</property> 
 		<!-- 最大的PreparedStatement的数量 -->   
 		<property name="c3p0.max_statements">50</property>** 
        
  		<mapping resource="com/java1234/model/Student.hbm.xml"/>
  	
    </session-factory>

</hibernate-configuration>

->运行程序:
Hibernate:select * from t_student
三条学生记录一并查出

2.配置日志框架 Log4J

Log4J 作为一个开源的优秀日志框架,被广泛使用,Hibernate4 必须包中直接支持 Log4J 日志框架;我们只需 要引入 Log4jjar 包,即可使用;
Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
第一步
加入log4j-1.2.8.jar(可以选择log4j的更高版本)到lib下。
如果使用maven项目,也可以选择在pom.xml中新增依赖:

<!-- 加入log4j支持 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>

第二步
在CLASSPATH下建立log4j.properties。内容如下(数字为行号):

log4j.rootCategory=INFO, stdout , R
 
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n
 
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=D:\\Tomcat 5.5\\logs\\qc.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n
 
log4j.logger.com.neusoft=DEBUG
log4j.logger.com.opensymphony.oscache=ERROR
log4j.logger.net.sf.navigator=ERROR
log4j.logger.org.apache.commons=ERROR
log4j.logger.org.apache.struts=WARN
log4j.logger.org.displaytag=ERROR
log4j.logger.org.springframework=DEBUG
log4j.logger.com.ibatis.db=WARN
log4j.logger.org.apache.velocity=FATAL
 
log4j.logger.com.canoo.webtest=WARN
 
log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN
log4j.logger.org.hibernate=DEBUG
log4j.logger.org.logicalcobwebs=WARN

第三步
相应的修改其中属性,修改之前就必须知道这些都是干什么的,在第二部分讲解。
第四步
在要输出日志的类中加入相关语句:
定义属性:static Logger logger = Logger.getLogger(LogDemo.class); //LogDemo为相关的类
在相应的方法中:
if (logger.isDebugEnabled()){
logger.debug(“System ……”);
}

扫描二维码关注公众号,回复: 3674416 查看本文章

按不同的日志等级输出日志到不同的文件中,例如error文件中只有输出的log级别为error的日志,info级别的日志只输出到info文件(所以这里需要用的是log4j的xml配置文件而不是使用log4j.properties文件)先说下log4j的几种log级别的等级:日志记录器(Logger)的行为是分等级的。
分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别,这些级别是从高到低的级别。Log4j建议只使用四个级别,优先级从高到低分别是 ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别, 则应用程序中所有DEBUG级别的日志信息将不被打印出来优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来。程序会打印高于或等于所设置级别的日志,设置的日志等级越高,打印出来的日志就越少。如果设置级别为INFO,则优先级高于等于INFO级别(如:INFO、WARN、ERROR)的日志信息将可以被输出,小于该级别的如DEBUG将不会被输出。所以从上面来说我们最好设置的日志级别为INFO ,或者是DEBUG级别。推荐使用DEBUG级别,可以显示所有的日志。

Log4j由三个重要的组成构成:日志记录器(Loggers),输出端(Appenders)和日志格式化器(Layout)。

1.Logger:控制要启用或禁用哪些日志记录语句,并对日志信息进行级别限制

2.Appenders : 指定了日志将打印到控制台还是文件中

3.Layout : 控制日志信息的显示格式
1、log4j.rootCategory=INFO, stdout , R
此句为将等级为INFO的日志信息输出到stdout和R这两个目的地,stdout和R的定义在下面的代码,可以任意起名。等级可分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL,如果配置OFF则不打出任何信息,如果配置为INFO这样只显示INFO、WARN、ERROR的log信息,而DEBUG信息不会被显示,具体讲解可参照第三部分定义配置文件中的logger。
2、log4j.appender.stdout=org.apache.log4j.ConsoleAppender
此句为定义名为stdout的输出端是哪种类型,可以是
org.apache.log4j.ConsoleAppender(控制台),
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
具体讲解可参照第三部分定义配置文件中的Appender。
3、log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
此句为定义名为stdout的输出端的layout是哪种类型,可以是
org.apache.log4j.HTMLLayout(以HTML表格形式布局),
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
具体讲解可参照第三部分定义配置文件中的Layout。
4、log4j.appender.stdout.layout.ConversionPattern= [QC] %p [%t] %C.%M(%L) | %m%n
如果使用pattern布局就要指定的打印信息的具体格式ConversionPattern,打印参数如下:
%m 输出代码中指定的消息;
%M 输出打印该条日志的方法名;
%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL;
%r 输出自应用启动到输出该log信息耗费的毫秒数;
%c 输出所属的类目,通常就是所在类的全名;
%t 输出产生该日志事件的线程名;
%n 输出一个回车换行符,Windows平台为"rn”,Unix平台为"n”;
%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyyy-MM-dd HH:mm:ss,SSS},输出类似:2002-10-18 22:10:28,921;
%l 输出日志事件的发生位置,及在代码中的行数;
[QC]是log信息的开头,可以为任意字符,一般为项目简称。
输出的信息
[TS] DEBUG [main] AbstractBeanFactory.getBean(189) | Returning cached instance of singleton bean ‘MyAutoProxy’
具体讲解可参照第三部分定义配置文件中的格式化日志信息。
5、log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
此句与第3行一样。定义名为R的输出端的类型为每天产生一个日志文件。
6、log4j.appender.R.File=D:\Tomcat 5.5\logs\qc.log
此句为定义名为R的输出端的文件名为D:\Tomcat 5.5\logs\qc.log可以自行修改。
7、log4j.appender.R.layout=org.apache.log4j.PatternLayout
与第4行相同。
8、log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n
与第5行相同。
9、log4j.logger.com. neusoft =DEBUG
指定com.neusoft包下的所有类的等级为DEBUG。
可以把com.neusoft改为自己项目所用的包名。
10、log4j.logger.com.opensymphony.oscache=ERROR
11、log4j.logger.net.sf.navigator=ERROR
这两句是把这两个包下出现的错误的等级设为ERROR,如果项目中没有配置EHCache,则不需要这两句。
12、log4j.logger.org.apache.commons=ERROR
13、log4j.logger.org.apache.struts=WARN
这两句是struts的包。
14、log4j.logger.org.displaytag=ERROR
这句是displaytag的包。(QC问题列表页面所用)
15、log4j.logger.org.springframework=DEBUG
此句为Spring的包。
16、log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN
17、log4j.logger.org.hibernate=DEBUG
此两句是hibernate的包。
以上这些包的设置可根据项目的实际情况而自行定制。

在项目 Hibernate11中
新建包log4j
导入jar包log4j-1.2.17
->log4j.txt

log4j.rootLogger=info,appender1,appender2

log4j.appender.appender1=org.apache.log4j.ConsoleAppender //控制台输出

log4j.appender.appender2=org.apache.log4j.FileAppender //文件输出
log4j.appender.appender2.File=C:/logFile.txt
 
log4j.appender.appender1.layout=org.apache.log4j.TTCCLayout
log4j.appender.appender2.layout=org.apache.log4j.TTCCLayout  

->StudentTest.java

 package com.java1234.service;


import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.java1234.model.Student;
import com.java1234.util.HibernateUtil;

public class StudentTest {

	private SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
	private Session session;
	**private Logger logger=Logger.getLogger(StudentTest.class);**
	
	@Before
	public void setUp() throws Exception {
		session=sessionFactory.openSession(); // 生成一个session
	    session.beginTransaction(); // 开启事务
	}

	@After
	public void tearDown() throws Exception {
		 session.getTransaction().commit(); // 提交事务
		 session.close(); // 关闭session
	}

	@Test
	public void testSQLQuery() {
		String sql="select * from t_student";
		Query query=session.createSQLQuery(sql).addEntity(Student.class);
		List studentList=query.list();
		Iterator it=studentList.iterator();
		while(it.hasNext()){
			Student s=(Student)it.next();
			System.out.println(s);
		}	
		logger.debug("这是一个debug信息");
		logger.info("这是一个info信息");
		logger.error("这是一个错误信息");
	}	
}

->启动程序
在这里插入图片描述

在这里插入图片描述

3.配置 Hibernate 二级缓存

1,缓存的概念: 缓存是介于物理数据源与应用程序之间,是对数据库中的数据复制一份临时放在内存或者硬盘中的容 器,其作用是为了减少应用程序对物理数据源访问的次数,从而提高了应用程序的运行性能。Hibernate 在进 行读取数据的时候,根据缓存机制在相应的缓存中查询,如果在缓存中找到了需要的数据(我们把这称做“缓 存命 中"),则就直接把命中的数据作为结果加以利用,避免了大量发送 SQL 语句到数据库查询的性能损耗。
2,Hibernate 缓存的分类:
一、Session 缓存(又称作事务缓存):Hibernate 内置的,不能卸除。 缓存范围:缓存只能被当前 Session 对象访问。缓存的生命周期依赖于 Session 的生命周期,当 Session 被关闭 后,缓存也就结束生命周期。
二、SessionFactory 缓存(又称作应用缓存):使用第三方插件,可插拔。 缓存范围:缓存被应用范围内的所有 session 共享,不同的 Session 可以共享。这些 session 有可能是并发访问缓 存,因此必须对缓存进行更新。缓存的生命周期依赖于应用的生命周期,应用结束时,缓存也就结束了生命 周期,二级缓存存在于应用程序范围。
新建项目Hibernate11-02
->StudentTest.java

package com.java1234.service;

import static org.junit.Assert.*; 

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import com.java1234.model.Class;
import com.java1234.model.Student;
import com.java1234.util.HibernateUtil;

public class StudentTest {

	private SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
	private Session session;
	
	/*@Before
	public void setUp() throws Exception {
		session=sessionFactory.openSession(); // 生成一个session
	    session.beginTransaction(); // 开启事务
	}

	@After
	public void tearDown() throws Exception {
		 session.getTransaction().commit(); // 提交事务
		 session.close(); // 关闭session
	}*/

	@Test
	public void testCache1() {//在同一个事务中 
		Class c=(Class)session.get(Class.class, Long.valueOf(1));
		System.out.println(c.getName());
		Class c2=(Class)session.get(Class.class, Long.valueOf(1));
		System.out.println(c2.getName());
		System.out.println(c==c2);
	}
	//Hibernate:select class0_.classId as classId1_0_0_,class0_.className这个只执行一条
	//08计算机本科
	//08计算机本科
	//true
	
	@Test
	public void testCache2(){//在不同事物当中
		Session session1=sessionFactory.openSession();
		session1.beginTransaction();
		Class c=(Class)session1.get(Class.class, Long.valueOf(1));
		System.out.println(c.getName());
		session1.getTransaction().commit();
		session1.close();
		
		Session session2=sessionFactory.openSession();
		session2.beginTransaction();
		Class c2=(Class)session2.get(Class.class, Long.valueOf(1));
		System.out.println(c2.getName());
		session2.getTransaction().commit();
		session2.close();
		
		System.out.println(c==c2);
	}
	 //Hibernate:select class0_.classId as classId1_0_0_,class0_.className
	//08计算机本科
	 //Hibernate:select class0_.classId as classId1_0_0_,class0_.className
	//08计算机本科
	//false

}

3,二级缓存策略提供商: 提供了 HashTable 缓存,EHCache,OSCache,SwarmCache,jBoss Cathe2,这些缓存机制,其中 EHCache, OSCache 是不能用于集群环境(Cluster Safe)的,而 SwarmCache,jBoss Cathe2 是可以的。HashTable 缓存主 要是用来测试的,只能把对象放在内存中,EHCache,OSCache 可以把对象放在内存(memory)中,也可以 把对象放在硬盘(disk)上(为什么放到硬盘上?上面解释了)。
4,什么数据适合放二级缓存中: (1)经常被访问 (2)改动不大 (3)数量有限 (4)不是很重要的数据,允许出现偶尔并发的数据。 比如组织机构代码,列表信息等;
5,配置 EHCache 二级缓存;

二级缓存要先配置jar包
->新建包ehcache,导入3个包,
ehcache-core-2.4.3
hibernate-ehcache-4.3.5.Final
slfj-qpi-1.6.1
->配置文件ehcache.xml

<ehcache>
   
   	<!-- 指定一个文件目录,当EHCache把数据写到硬盘上时,将把数据写到这个目录下 -->
    <diskStore path="c:\\ehcache"/>
    
    <!--  
    	设置缓存的默认数据过期策略 
    -->    
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />

	<!-- 
		name 设置缓存的名字,他的取值为类的完整名字或者类的集合的名字;
		maxElementsInMemory 设置基于内存的缓存可存放的对象的最大数目
		eternal 如果为true,表示对象永远不会过期,此时会忽略timeToIdleSeconds和timeToLiveSeconds,默认为false;
		timeToIdleSeconds 设定允许对象处于空闲状态的最长时间,以秒为单位;
		timeToLiveSeconds 设定对象允许存在于缓存中的最长时间,以秒为单位;
		overflowToDisk 如果为true,表示当基于内存的缓存中的对象数目达到maxElementsInMemory界限,会把溢出的对象写到基于硬盘的缓存中;
	 -->


	<!-- 设定具体的第二级缓存的数据过期策略 -->
    <cache name="com.java1234.model.Class"
        maxElementsInMemory="1"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />
 

</ehcache>

->配置hibernate.cfg.xml

<?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/hibernate</property>
        <property name="connection.username">root</property>
        <property name="connection.password">123456</property>

       
        <!-- 方言 -->
        <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
	
        <!-- 控制台显示SQL -->
        <property name="show_sql">true</property>

        <!-- 自动更新表结构 -->
        <property name="hbm2ddl.auto">update</property>
        
         **<!-- 启用二级缓存 -->
		<property name="cache.use_second_level_cache">true</property>
    	
    	<!-- 配置使用的二级缓存的产品 -->
    	<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
    	
    	<!-- 配置启用查询缓存 -->
    	<property name="cache.use_query_cache">true</property>**
        
  		<mapping resource="com/java1234/model/Student.hbm.xml"/>
  		
  		<mapping resource="com/java1234/model/Class.hbm.xml"/>

    </session-factory>

</hibernate-configuration>

->Student.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.java1234.model">

	<class name="Class" table="t_class">
		**<cache usage="read-only"/>**//这里要配置才能使用二级缓存
		<id name="id" column="classId">
			<generator class="native"></generator>
		</id>
		
		<property name="name" column="className"></property>
	</class>

</hibernate-mapping>

->StudentTest.java

package com.java1234.service;

import static org.junit.Assert.*;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import com.java1234.model.Class;
import com.java1234.model.Student;
import com.java1234.util.HibernateUtil;

public class StudentTest {

	private SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
	private Session session;
	
	/*@Before
	public void setUp() throws Exception {
		session=sessionFactory.openSession(); // 生成一个session
	    session.beginTransaction(); // 开启事务
	}

	@After
	public void tearDown() throws Exception {
		 session.getTransaction().commit(); // 提交事务
		 session.close(); // 关闭session
	}*/

	@Test
	public void testCache1() {
		Class c=(Class)session.get(Class.class, Long.valueOf(1));
		System.out.println(c.getName());
		Class c2=(Class)session.get(Class.class, Long.valueOf(1));
		System.out.println(c2.getName());
		System.out.println(c==c2);
	}
	
	@Test
	public void testCache2(){
		Session session1=sessionFactory.openSession();
		session1.beginTransaction();
		Class c=(Class)session1.get(Class.class, Long.valueOf(1));
		System.out.println(c.getName());
		session1.getTransaction().commit();
		session1.close();
		
		Session session2=sessionFactory.openSession();
		session2.beginTransaction();
		Class c2=(Class)session2.get(Class.class, Long.valueOf(1));
		System.out.println(c2.getName());
		session2.getTransaction().commit();
		session2.close();
		
		System.out.println(c==c2);
	}
	//用上了二级缓存,只输出一条sql语句  true

}

猜你喜欢

转载自blog.csdn.net/AthlenaA/article/details/82844772