频道栏目
首页 > 资讯 > Java > 正文

Hibernate 缓存详解

15-05-23        来源:[db:作者]  
收藏   我要投稿

Hibernate 缓存详解

session 一级缓存

1、session 一级缓存所持有的方法特征如下图:

data-cke-saved-src=/uploadfile/Collfiles/20150522/20150522084556345.png

详解:

flush:Session 按照缓存中对象的属性变化来同步更新数据库
默认情况下 Session 在以下时间点刷新缓存:
显式调用 Session 的 flush() 方法
当应用程序调用 Transaction 的 commit()方法的时, 该方法先 flush ,然后在向数据库提交事务
当应用程序执行一些查询(HQL, Criteria)操作时,如果缓存中持久化对象的属性已经发生了变化,会先 flush 缓存,以保证查询结果能够反映持久化对象的最新状态
flush 缓存的例外情况: 如果对象使用 native 生成器生成 OID, 那么当调用 Session 的 save() 方法保存对象时, 会立即执行向数据库插入该实体的 insert 语句.
commit() 和 flush() 方法的区别:flush 执行一系列 sql 语句,但不提交事务;commit 方法先调用flush() 方法,然后提交事务. 意味着提交事务意味着对数据库操作永久保存下来。

程序设计

flush() 方法

	/**
	 * flush: 使数据表中的记录和 Session 缓存中的对象的状态保持一致. 为了保持一致, 则可能会发送对应的 SQL 语句.
	 * 1. 在 Transaction 的 commit() 方法中: 先调用 session 的 flush 方法, 再提交事务
	 * 2. flush() 方法会可能会发送 SQL 语句, 但不会提交事务. 
	 * 3. 注意: 在未提交事务或显式的调用 session.flush() 方法之前, 也有可能会进行 flush() 操作.
	 * 1). 执行 HQL 或 QBC 查询, 会先进行 flush() 操作, 以得到数据表的最新的记录 -- 先查询了一次,然后再HQL,隐身的调用了flush
	 * 2). 若记录的 ID 是由底层数据库使用自增的方式生成的, 则在调用 save() 方法时, 就会立即发送 INSERT 语句. 
	 * 因为 save 方法后, 必须保证对象的 ID 是存在的!
	 */
	@Test
	public void testSessionFlush2(){
		News news = new News(Java, SUN, new Date());
		session.save(news);
	}
	
	@Test
	public void testSessionFlush(){
		News news = (News) session.get(News.class, 1);
		news.setAuthor(Oracle);
		
    	session.flush();
		//在外部一定要commit();这样就会将java中的改变,以及session中的缓存存入oracle中,看到效果

		News news2 = (News) session.createCriteria(News.class).uniqueResult();
		System.out.println(news2);
	}
	
	@Test
	public void testSessionCache(){
		
		News news = (News) session.get(News.class, 1);
		System.out.println(news); 
		
		News news2 = (News) session.get(News.class, 1);
		System.out.println(news2);
	}

 

reflush()方法

	/**
	 * refresh(): 会强制发送 SELECT 语句, 以使 Session 缓存中对象的状态和数据表中对应的记录保持一致!
	 */
	@Test
	public void testRefresh(){
		News news = (News) session.get(News.class, 1);
		System.out.println(news);
		
		session.refresh(news); 
		System.out.println(news); 
	}

 

clear()方法

	/**
	 * clear(): 清理缓存
	 */
	@Test
	public void testClear(){
		News news1 = (News) session.get(News.class, 1);
		
		session.clear();
		
		News news2 = (News) session.get(News.class, 1);
	}

 

session 二级缓存

解析:

1. 使用 Hibernate 二级缓存的步骤:

1). 加入二级缓存插件的 jar 包及配置文件:

I. 复制 hibernate-release-4.2.4.Finalliboptionalehcache*.jar 到当前 Hibrenate 应用的类路径下.
II. 复制 hibernate-release-4.2.4.Finalprojectetcehcachexml 到当前 WEB 应用的类路径下

2). 配置 hibernate.cfg.xml 

I.   配置启用 hibernate 的二级缓存
true

II.  配置hibernate二级缓存使用的产品
org.hibernate.cache.ehcache.EhCacheRegionFactory

III. 配置对哪些类使用 hibernate 的二级缓存

  
实际上也可以在 .hbm.xml 文件中配置对哪些类使用二级缓存, 及二级缓存的策略是什么. 

2). 集合级别的二级缓存的配置

I. 配置对集合使用二级缓存



也可以在 .hbm.xml 文件中进行配置


 
    
        
    
    


II. 注意: 还需要配置集合中的元素对应的持久化类也使用二级缓存! 否则将会多出 n 条 SQL 语句. 

3). ehcache 的 配置文件: ehcache.xml

4).  查询缓存: 默认情况下, 设置的缓存对 HQL 及 QBC 查询时无效的, 但可以通过以下方式使其是有效的

I.  在 hibernate 配置文件中声明开启查询缓存

true

II. 调用 Query 或 Criteria 的 setCacheable(true) 方法

III. 查询缓存依赖于二级缓存

 

项目试验

项目清单

data-cke-saved-src=/uploadfile/Collfiles/20150522/20150522084556346.png

项目源码及分析

1、package com.atguigu.hibernate.helloworld

package com.atguigu.hibernate.helloworld;

import java.sql.Blob;
import java.util.Date;
import java.util.Set;

public class News {
	
	private Integer id; //field
	private String title;
	private String author;
	
	private Date date;
	
	private Set peoples;

	
	public Set getPeoples() {
		return peoples;
	}

	public void setPeoples(Set peoples) {
		this.peoples = peoples;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public Date getDate() {
		return date;
	}

	public void setDate(Date date) {
		this.date = date;
	}

	public News(String title, String author, Date date,Set peoples) {
		this.title = title;
		this.author = author;
		this.date = date;
		this.peoples = peoples;
	}
	
	public News() {
	}
}
package com.atguigu.hibernate.helloworld;
/**
 * 发送News人员 
 */
public class People {
private Integer id;
private String name;
private News news;

public News getNews() {
	return news;
}
public void setNews(News news) {
	this.news = news;
}
public Integer getId() {
	return id;
}
public void setId(Integer id) {
	this.id = id;
}
public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}
public People() {
}
public People(Integer id, String name,News news) {
	this.id = id;
	this.name = name;
	this.news = news;
}
}
package com.atguigu.hibernate.helloworld;

import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class SessionSecondCache {
	private SessionFactory sessionFactory;
	private Session session;
	private Transaction transaction;
	
	@Before
	public void init(){
		Configuration configuration = new Configuration().configure();
		ServiceRegistry serviceRegistry = 
				new ServiceRegistryBuilder().applySettings(configuration.getProperties())
				                            .buildServiceRegistry();
		sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
	}
	
	@After
	public void destroy(){
		sessionFactory.close();
	}
	@Test
	public void testHiberneteSecondCache(){
		News news = (News) session.get(News.class, 1);
		Set peoples = news.getPeoples();
		System.out.println(peoples.size());
		transaction.commit();
		session.close();
		
		Session session2 = sessionFactory.openSession();
		transaction = session2.beginTransaction();
		News news2 = (News) session2.get(News.class, 1);
		Set peoples2 = news2.getPeoples();
		System.out.println(peoples2.size());
	}
}

 

2、ehcache.xml



    
         
    


    
        
    

   	
   	

 

3、hibernate.cfg.xml




	
    
		
		root
		123456
		com.mysql.jdbc.Driver
		jdbc:mysql:///hibernate5
		
		
		
		org.hibernate.dialect.MySQLInnoDBDialect		
		
		
		true
	
		
		true
	
		
		update
		
		
		true
    	
    	
    	org.hibernate.cache.ehcache.EhCacheRegionFactory
    	
    	
    	true
    	
		
		
		
	
	    
	    
		
		
	



4、sql 脚本

  CREATE TABLE NEWS (
        ID INTEGER NOT NULL AUTO_INCREMENT,
        TITLE VARCHAR(255) NOT NULL,
        AUTHOR VARCHAR(255),
        DATE DATE,
        PRIMARY KEY (ID)
    )
    
  CREATE TABLE People (
        ID INTEGER NOT NULL AUTO_INCREMENT,
        NAME VARCHAR(255) NOT NULL,
        n_id INTEGER,
        PRIMARY KEY (ID)
    )
    
        ALTER TABLE NEWS 
        ADD CONSTRAINT UK_duq2gjdo5k53otrakypw0888b UNIQUE (TITLE)
        
        ALTER TABLE People 
        ADD CONSTRAINT UK_24fes2jfmnlqa29qtgceqvjoc UNIQUE (NAME)
        
        ALTER TABLE People 
        ADD INDEX FK_4ldntgu2n6tr9rlcq23ouvytd (n_id), 
        ADD CONSTRAINT FK_4ldntgu2n6tr9rlcq23ouvytd 
        FOREIGN KEY (n_id) 
        REFERENCES NEWS (ID)

 

 

相关TAG标签
上一篇:hihocoder #1042 : 跑马圈地
下一篇:hdu4751 最短路+背包dp
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站