@ManyToOne(fetch=FetchType.LAZY)
@OneToMany(fetch=FetchType.LAZY)
@BatchSize(size=100)
public class Category
@ManyToOne
@BatchSize(size=5)
public Category getCategory() {
return category;
}
List<Topic> lists = (List<Topic>)session.createQuery("from Topic t left join t.category").list();
//Criteria默认使用外连接
// List<Topic> lists = (List<Topic>)session
// .createCriteria(Topic.class)
// .list();
/**
* 首先将查询的主键获取
* Hibernate:
select
topic0_.id as col_0_0_
from
Topic topic0_
* @return @void
*/
@Test
public void testItrator()
{
session.beginTransaction();
Query q1 = session.createQuery("from Topic t");
Iterator<Topic> topics = q1.iterate();
q1.setCacheable(true);
session.getTransaction().commit();
}
/**
* Iterator
* 每次查询后将结果放入session,
* 在同一生命周期的session,iterate查询 如果session有将不会再到数据库查找,直接返回值
* @return @void
*/
@Test
public void testIterator1()
{
session.beginTransaction();
Query q1 = session.createQuery("from Topic t");
Iterator<Topic> ts = q1.iterate();
while(ts.hasNext())
{
Topic t = ts.next();
System.out.println("Topic :"+t.getTitle());
}
Query q2 = session.createQuery("from Topic t");
Iterator<Topic> ts2 = q2.iterate();
while(ts2.hasNext())
{
Topic t = ts.next();
System.out.println("Topic :"+t.getTitle());
}
session.getTransaction().commit();
}
/**
* List每次默认发出sql查询
* @return @void
*/
@Test
public void testList1()
{
session.beginTransaction();
Query q1 = session.createQuery("from Topic t");
List<Topic> list1 = q1.list();
for(Topic t :list1)
{
log.debug("Topic :"+t);
}
Query q2 = session.createQuery("from Topic t");
List<Topic> list2 = q2.list();
for(Topic t :list2)
{
log.debug("Topic :"+t);
}
session.getTransaction().commit();
}
缓存 | 原理 | 生命周期 | 配置 | 方法 | 管理 |
一级缓存 | session级别的缓存 | session的生命周期 | 无 | ● get, ● load, ● iterate |
● evit(Object obj)
● clear()
● contains(Object obj)
● flush()
|
二级缓存 |
二级缓存也称为进程级的缓存,也可称为SessionFactory级的缓存(因为SessionFactory可以管理二级缓存)
二级缓存可以被所有的session共享,
二级缓存同session级缓存一样,只缓存实体对象,普通属性的查询不会缓存
二级缓存一般使用第三方的产品,如EHCache
| 二级缓存的生命周期和SessionFactory的生命周期一样,SessionFactory可以管理二级缓存 | ● jar包 ● ehcache.xml ● hibernate.cfg.xml
<
property name
=
"cache.use_second_level_cache"
>
true
</
property
>
<!-- 注意三者区别 -->
<!-- hibernte 3
<property name="cache.provider_class">
org.hibernate.cache.EhCacheRegionFactory
</property>-->
<!-- hibernte 4.2
<property name="cache.region.factory_class">
org.hibernate.cache。ehcache.EhCacheRegionFactory
</property>-->
<!-- hibernte 4.3.10 -->
<property name="cache.region.factory_class">
org.hibernate.cache.ehcache.EhCacheRegionFactory
</property>
● entity类
@Entity
@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Category
|
● load默认使用二级缓存,
● iterate默认使用二级缓存
● list默认向二级缓存中加数据,但是查询时候不使用
| ● evict ● 注意4.3.10版本放弃了evict,改用getCache()统一管理 |
查询缓存 | 查询缓存 key值是hql,value值是实体主键,主要作用是缓存普通属性查询。 | 当前关联的表发生修改,那么查询缓存生命周期结束 |
<!-- 打开查询缓存 -->
<property name="cache.use_query_cache">true</property>
| ●list ●iterator不起作用 | 无 |
/**
* 控制台输出:
* Hibernate:
select
category0_.id as id1_0_0_,
category0_.name as name2_0_0_
from
Category category0_
where
category0_.id=?
Category :com.liuhao.hibernate4.demo.query2.Category@98bbf6[id=1,name=c0]
Category :com.liuhao.hibernate4.demo.query2.Category@98bbf6[id=1,name=c0]
* @return @void
*/
@Test
public void testGet()
{
session.beginTransaction();
Category c1 = (Category) session.get(Category.class, 1);
Category c2 = (Category) session.get(Category.class, 1);
System.out.println("Category :"+c1);
System.out.println("Category :"+c2);
session.getTransaction().commit();
}
/**
* 控制台输出:
* Hibernate:
select
category0_.id as id1_0_0_,
category0_.name as name2_0_0_
from
Category category0_
where
category0_.id=?
Category :com.liuhao.hibernate4.demo.query2.Category@98bbf6[id=1,name=c0]
Category :com.liuhao.hibernate4.demo.query2.Category@98bbf6[id=1,name=c0]
* @return @void
*/
@Test
public void testLoad()
{
session.beginTransaction();
Category c1 = (Category) session.load(Category.class, 1);
Category c2 = (Category) session.load(Category.class, 1);
System.out.println("Category :"+c1);
System.out.println("Category :"+c2);
session.getTransaction().commit();
}
/**
* Hibernate:
select
category0_.id as col_0_0_
from
Category category0_
where
category0_.id=1
Hibernate:
select
category0_.id as col_0_0_
from
Category category0_
where
category0_.id=1
Hibernate:
select
category0_.id as id1_0_0_,
category0_.name as name2_0_0_
from
Category category0_
where
category0_.id=?
Category :com.liuhao.hibernate4.demo.query2.Category@1bbbafc[id=1,name=c0]
Category :com.liuhao.hibernate4.demo.query2.Category@1bbbafc[id=1,name=c0]
* @return @void
*/
@Test
public void testIterate()
{
session.beginTransaction();
Iterator c1 = (Iterator) session.createQuery("from Category where id = 1").iterate();
Iterator c2 = (Iterator) session.createQuery("from Category where id = 1").iterate();
while(c1.hasNext())
{
Category c = (Category) c1.next();
System.out.println("Category :"+c);
}
while(c2.hasNext())
{
Category c = (Category) c2.next();
System.out.println("Category :"+c);
}
session.getTransaction().commit();
}
@Test
public void testClear()
{
session.beginTransaction();
Iterator c1 = (Iterator) session.createQuery("from Category where id = 1").iterate();
Iterator c2 = (Iterator) session.createQuery("from Category where id = 1").iterate();
while(c1.hasNext())
{
Category c = (Category) c1.next();
System.out.println("Category :"+c);
}
while(c2.hasNext())
{
Category c = (Category) c2.next();
System.out.println("Category :"+c);
}
//清除session
session.clear();
Iterator c3 = (Iterator) session.createQuery("from Category where id = 1").iterate();
while(c3.hasNext())
{
Category c = (Category) c3.next();
System.out.println("Category :"+c);
}
session.getTransaction().commit();
}
@Test
public void testEvict()
{
session.beginTransaction();
Category c1 = (Category) session.load(Category.class, 1);
Category c2 = (Category) session.load(Category.class, 1);
System.out.println("Category :"+c1);
System.out.println("Category :"+c2);
//清除的是放入session的对象 不能是Query,Iterator
session.evict(c1);
session.evict(c2);
Category c3 = (Category) session.load(Category.class, 1);
System.out.println("Category3 :"+c3);
session.getTransaction().commit();
}
create or replace procadure UserUpdate(u_age in number) as
begin
update users set age=age+1 where age>u_age;
end;
Session session =SessionFactory.openSession();
Transaction tx =session.beginTransaction();
Connection conn=session.connection();
String str="{call UserUpdate(?)}";
CallableStatement cstmt= conn.prepareCall(str);
cstmt.setInt(1,0);
cstmt.executeUpdate();
tx.commit();
sessionFactory.evict(Customer.class, new Integer(1));
sessionFactory.evict(Customer.class);
sessionFactory.evictCollection("Customer.orders");
Cache cache = sfactory.getCache();
//清除所有
cache.evictAllRegions();
//cache.evictEntityRegion(Category.class);//清除指定类
//cache.evictEntity(Category.class,1);//清除指定类的指定数据
/*清除集合
cache.evictCollectionRegions();
cache.evictCollectionRegion(arg0);
cache.evictCollection(arg0, arg1);
*/
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<!--如果缓存中的对象存储超过指定的缓存数量的对象存储的磁盘地址-->
<diskStore path="D:/ehcache"/>
<!-- 默认cache:如果没有对应的特定区域的缓存,就使用默认缓存 -->
<defaultCache maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="false"/>
<!-- 指定区域cache:通过name指定,name对应到Hibernate中的区域名即可-->
<cache name="cn.javass.h3test.model.UserModel"
eternal="false"
maxElementsInMemory="100"
timeToIdleSeconds="1200"
timeToLiveSeconds="1200"
overflowToDisk="false">
</cache>
</ehcache>
Cache | Provider class | Type | Cluster Safe | Query Cache Supported |
Hashtable (not intended for production use) | org.hibernate.cache.HashtableCacheProvider | memory |
| yes |
EHCache | org.hibernate.cache.EhCacheProvider | memory, disk |
| yes |
OSCache | org.hibernate.cache.OSCacheProvider | memory, disk |
| yes |
SwarmCache | org.hibernate.cache.SwarmCacheProvider | clustered (ip multicast) | yes (clustered invalidation) |
|
JBoss TreeCache | org.hibernate.cache.TreeCacheProvider | clustered (ip multicast), transactional | yes (replication) | yes (clock sync req.) |
<!-- 二级缓存默认打开,这里只是显示打开一下 -->
<property name="cache.use_second_level_cache">true</property>
<!-- 注意3和4者区别 -->
<!-- hibernte 3
<property name="cache.provider_class">
org.hibernate.cache.EhCacheRegionFactory
</property>-->
<!-- hibernte 4.3.10 -->
<property name="cache.region.factory_class">
org.hibernate.cache.ehcache.EhCacheRegionFactory
</property>
@Entity
@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Category {
private int id;
private String name;
@Id
@GeneratedValue
public int getId() {
return id;
}
//set get...
}
//确保数据库中有标识符为1的FarmModel
FarmModel farm = (FarmModel) session.get(FarmModel.class, 1);
//如果修改将报错,只读缓存不允许修改
//farm.setName("aaa");
@Cache(usage =CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public SortedSet<Ticket> getTickets(){
return tickets;
}
@Test
public void testload()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session = sfactory.openSession();
session.beginTransaction();
Category c1 = (Category) session.load(Category.class,1);
System.out.println("Category :"+c1);
session.close();
//第二个session但是SessionFactory没有关闭
Session session2 = sfactory.openSession();
Category c2 = (Category) session2.load(Category.class,1);
System.out.println("Category :"+c2);
session2.close();
sfactory.close();
}
@Test
public void testiterate()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session = sfactory.openSession();
session.beginTransaction();
Query q1 = (Query) session.createQuery("from Category where name='c0'");
Iterator<?> iterator = q1.iterate();
while(iterator.hasNext())
{
Category c = (Category) iterator.next();
System.out.println("Category :"+c);
}
session.close();
//第二个session但是SessionFactory没有关闭
Session session2 = sfactory.openSession();
Query q2 = (Query) session2.createQuery("from Category where name='c0'");
Iterator<?> iterator2 = q2.iterate();
while(iterator2.hasNext())
{
Category c = (Category) iterator2.next();
System.out.println("Category :"+c);
}
session2.close();
sfactory.close();
}
@Test
public void testiterate_load() {
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session = sfactory.openSession();
session.beginTransaction();
Query q1 = (Query) session.createQuery("from Category where name='c0'");
Iterator<?> iterator = q1.iterate();
while (iterator.hasNext()) {
Category c = (Category) iterator.next();
System.out.println("Category :" + c);
}
session.close();
// 第二个session但是SessionFactory没有关闭
Session session2 = sfactory.openSession();
Category c2 = (Category) session2.load(Category.class, 1);
System.out.println("Category :" + c2);
session2.close();
sfactory.close();
}
/**
*
* list 只存不取
* @return @void
*/
@SuppressWarnings("unchecked")
@Test
public void testlist_load() {
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session = sfactory.openSession();
session.beginTransaction();
Query q1 = (Query) session.createQuery("from Category where name='c0'");
for (Category c : (List<Category>)q1.list()) {
System.out.println("Category :" + c);
}
session.close();
// 第二个session但是SessionFactory没有关闭
Session session2 = sfactory.openSession();
Category c2 = (Category) session2.load(Category.class, 1);
System.out.println("Category :" + c2);
session2.close();
sfactory.close();
}
@Test
public void testEvict()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session = sfactory.openSession();
session.beginTransaction();
Category c1 = (Category) session.load(Category.class,1);
System.out.println("Category :"+c1);
session.close();
//4.3中evict过时,使用getCache
//sfactory.evict(Category.class);
Cache cache = sfactory.getCache();
//清除所有
cache.evictAllRegions();
//cache.evictEntityRegion(Category.class);//清除指定类
//cache.evictEntity(Category.class,1);//清除指定类的指定数据
/*清除集合
cache.evictCollectionRegions();
cache.evictCollectionRegion(arg0);
cache.evictCollection(arg0, arg1);
*/
//第二个session但是SessionFactory没有关闭
Session session2 = sfactory.openSession();
Category c2 = (Category) session2.load(Category.class,1);
System.out.println("Category :"+c2);
session2.close();
sfactory.close();
}
CacheMode参数用于控制具体的Session如何与二级缓存进行交互。
CacheMode.NORMAL - 从二级缓存中读、写数据。
CacheMode.IGNORE- session不会与二级缓存交互。
CacheMode.GET - 从二级缓存中读取数据,仅在数据更新时对二级缓存写数据。
CacheMode.PUT - 仅向二级缓存写数据,但不从二级缓存中读数据。
CacheMode.REFRESH - 仅向二级缓存写数据,但不从二级缓存中读数据。通过hibernate.cache.use_minimal_puts(是否优化二级缓存操作,最小化缓存写入操作(适用与集群缓存))的设置,强制二级缓存从数据库中读取数据,刷新缓存内容。
如若需要查看二级缓存或查询缓存区域的内容,你可以使用统计(Statistics) API。
Map cacheEntries = sessionFactory.getStatistics()
.getSecondLevelCacheStatistics(regionName)
.getEntries();
此时,你必须手工打开统计选项。可选的,你可以让Hibernate更人工可读的方式维护缓存内容。
hibernate.generate_statistics true
hibernate.cache.use_structured_entries true
/**
* 从二级缓存中读取数据,仅在数据更新时对二级缓存写数据。
* @return @void
*/
@Test
public void testMutual_GET()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session1 = sfactory.openSession();
session1.setCacheMode(CacheMode.GET);
Category c1 = (Category) session1.load(Category.class, 1);
System.out.println("Category :"+c1);
session1.close();
System.out.println("-----------------------");
long count = sfactory.getStatistics()
.getSecondLevelCachePutCount();
System.out.println("Cache : "+count);
Session session2 = sfactory.openSession();
//不能取 所有两条sql
Category c2 = (Category) session2.load(Category.class, 1);
System.out.println("Category :"+c2);
session2.close();
sfactory.close();
}
/**
* 仅向二级缓存写数据,但不从二级缓存中读数据。
* @return @void
*/
@Test
public void testMutual_PUT()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session1 = sfactory.openSession();
session1.setCacheMode(CacheMode.PUT);
Category c1 = (Category) session1.load(Category.class, 1);
System.out.println("Category :"+c1);
session1.close();
System.out.println("-----------------------");
long count = sfactory.getStatistics()
.getSecondLevelCachePutCount();
System.out.println("Cache : "+count);
Session session2 = sfactory.openSession();
//一条sql 二级缓存有 且能取
Category c2 = (Category) session2.load(Category.class, 1);
System.out.println("Category :"+c2);
session2.close();
sfactory.close();
}
/**
* 仅向二级缓存写数据,但不从二级缓存中读数据。
* 通过hibernate.cache.use_minimal_puts
* (是否优化二级缓存操作,最小化缓存写入操作(适用与集群缓存))的设置,
* 强制二级缓存从数据库中读取数据,刷新缓存内容。
* @return @void
*/
@Test
public void testMutual_REFRESH()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session1 = sfactory.openSession();
Category c1 = (Category) session1.load(Category.class, 1);
System.out.println("Category :"+c1);
session1.close();
System.out.println("-----------------------");
long count = sfactory.getStatistics()
.getSecondLevelCachePutCount();
System.out.println("Cache : "+count);
Session session2 = sfactory.openSession();
session2.setCacheMode(CacheMode.REFRESH);
//两条sql 二级缓存有 但不能取
Category c2 = (Category) session2.load(Category.class, 1);
System.out.println("Category :"+c2);
session2.close();
sfactory.close();
}
/**
* session与二级缓存之间没有交互
* @return @void
*/
@Test
public void testMutual_IGONORE()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session1 = sfactory.openSession();
session1.setCacheMode(CacheMode.IGNORE);
Category c1 = (Category) session1.load(Category.class, 1);
System.out.println("Category :"+c1);
session1.close();
System.out.println("-----------------------");
long count = sfactory.getStatistics()
.getSecondLevelCachePutCount();
System.out.println("Cache : "+count);
Session session2 = sfactory.openSession();
//两条sql 二级缓存有 但不能取
Category c2 = (Category) session2.load(Category.class, 1);
System.out.println("Category :"+c2);
session2.close();
sfactory.close();
}
<!-- 打开查询缓存 -->
<property name="cache.use_query_cache">true</property>
<!-- 二级缓存默认打开,这里只是显示打开一下 -->
<property name="cache.use_second_level_cache">true</property>
<!-- 注意3和4区别 -->
<!-- hibernte 3
<property name="cache.provider_class">
org.hibernate.cache.EhCacheRegionFactory
</property>
-->
<!-- hibernte 4.3.10 -->
<property name="cache.region.factory_class">
org.hibernate.cache.ehcache.EhCacheRegionFactory
</property>
@Entity
@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Category
Query q = session.createQuery("from Category where name = 'c0'");
//手动打开查询缓存
q.setCacheable(true);
public void testquerylist(SessionFactory sfactory)
{
Session session = sfactory.openSession();
session.beginTransaction();
Query q = session.createQuery("from Category where name = 'c0'");
q.setCacheable(true);
List<Category> list = (List<Category>)q.list();
for(Category c : list)
{
System.out.println("Category : "+c);
}
session.getTransaction().commit();
session.close();
}
public void testqueryiterator(SessionFactory sfactory)
{
Session session = sfactory.openSession();
session.beginTransaction();
Query q = session.createQuery("from Category where name = 'c0'");
q.setCacheable(true);
Iterator iterate = q.iterate();
while(iterate.hasNext())
{
Category c = (Category) iterate.next();
System.out.println("Category : "+c);
}
session.getTransaction().commit();
session.close();
}
/**
* 第一次list 查询
Hibernate:
select
category0_.id as id1_0_,
category0_.name as name2_0_
from
Category category0_
where
category0_.name='c0'
Category : com.liuhao.hibernate4.demo.query2.Category@17b2b2[id=1,name=c0]
第二次list 查询
Hibernate:
select
category0_.id as id1_0_0_,
category0_.name as name2_0_0_
from
Category category0_
where
category0_.id=?
Category : com.liuhao.hibernate4.demo.query2.Category@43da1b[id=1,name=c0]
* 第一次会将发出sql,然后将满足条件的实体主键放入查询缓存中,
* 查询缓存中key是hql,value是查询到的实体主键
* 第二次发出sql时,list先到查询缓存中查询,获取满足条件的id然后到数据库获取实体属性,
* 如果没有直接到数据库查询
* @return @void
*/
@Test
public void testQuerylist_list()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
System.out.println("第一次list 查询");
testquerylist(sfactory);
System.out.println("第一次list 查询");
testquerylist(sfactory);
}
/**
* 第一次iterator 查询
Hibernate:
select
category0_.id as col_0_0_
from
Category category0_
where
category0_.name='c0'
Hibernate:
select
category0_.id as id1_0_0_,
category0_.name as name2_0_0_
from
Category category0_
where
category0_.id=?
Category : com.liuhao.hibernate4.demo.query2.Category@1c4a5ec[id=1,name=c0]
第二次iterator 查询
Hibernate:
select
category0_.id as col_0_0_
from
Category category0_
where
category0_.name='c0'
Hibernate:
select
category0_.id as id1_0_0_,
category0_.name as name2_0_0_
from
Category category0_
where
category0_.id=?
Category : com.liuhao.hibernate4.demo.query2.Category@21447f[id=1,name=c0]
iterator每次都是查询满足条件的实体主键,
然后到数据库中获取对应主键的实体属性
* @return @void
*/
@Test
public void testQueryiterate_iterate()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
System.out.println("第一次iterator 查询");
testqueryiterator(sfactory);
System.out.println("第一次iterator 查询");
testqueryiterator(sfactory);
}
/**
* 第一次list 查询
Hibernate:
select
category0_.id as id1_0_,
category0_.name as name2_0_
from
Category category0_
where
category0_.name='c0'
Category : com.liuhao.hibernate4.demo.query2.Category@17b2b2[id=1,name=c0]
第二次iterator 查询
Hibernate:
select
category0_.id as col_0_0_
from
Category category0_
where
category0_.name='c0'
Hibernate:
select
category0_.id as id1_0_0_,
category0_.name as name2_0_0_
from
Category category0_
where
category0_.id=?
Category : com.liuhao.hibernate4.demo.query2.Category@37165f[id=1,name=c0]
list 将查询到的实体主键放入查询缓存中,
literator对查询缓存的策略是不存,不取
* @return @void
*/
@Test
public void testQuerylist_iterate()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
System.out.println("第一次list 查询");
testquerylist(sfactory);
System.out.println("第二次iterator 查询");
testqueryiterator(sfactory);
}
/**
* 第一次iterator 查询
Hibernate:
select
category0_.id as col_0_0_
from
Category category0_
where
category0_.name='c0'
Hibernate:
select
category0_.id as id1_0_0_,
category0_.name as name2_0_0_
from
Category category0_
where
category0_.id=?
Category : com.liuhao.hibernate4.demo.query2.Category@1c4a5ec[id=1,name=c0]
第二次list 查询
Hibernate:
select
category0_.id as id1_0_,
category0_.name as name2_0_
from
Category category0_
where
category0_.name='c0'
Category : com.liuhao.hibernate4.demo.query2.Category@1a1ff9[id=1,name=c0]
* @return @void
*/
@Test
public void testQueryiterate_list()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
System.out.println("第一次iterator 查询");
testqueryiterator(sfactory);
System.out.println("第二次list 查询");
testquerylist(sfactory);
}
@ManyToOne(fetch=FetchType.LAZY)
@OneToMany(fetch=FetchType.LAZY)
@BatchSize(size=100)
public class Category
@ManyToOne
@BatchSize(size=5)
public Category getCategory() {
return category;
}
List<Topic> lists = (List<Topic>)session.createQuery("from Topic t left join t.category").list();
//Criteria默认使用外连接
// List<Topic> lists = (List<Topic>)session
// .createCriteria(Topic.class)
// .list();
/**
* 首先将查询的主键获取
* Hibernate:
select
topic0_.id as col_0_0_
from
Topic topic0_
* @return @void
*/
@Test
public void testItrator()
{
session.beginTransaction();
Query q1 = session.createQuery("from Topic t");
Iterator<Topic> topics = q1.iterate();
q1.setCacheable(true);
session.getTransaction().commit();
}
/**
* Iterator
* 每次查询后将结果放入session,
* 在同一生命周期的session,iterate查询 如果session有将不会再到数据库查找,直接返回值
* @return @void
*/
@Test
public void testIterator1()
{
session.beginTransaction();
Query q1 = session.createQuery("from Topic t");
Iterator<Topic> ts = q1.iterate();
while(ts.hasNext())
{
Topic t = ts.next();
System.out.println("Topic :"+t.getTitle());
}
Query q2 = session.createQuery("from Topic t");
Iterator<Topic> ts2 = q2.iterate();
while(ts2.hasNext())
{
Topic t = ts.next();
System.out.println("Topic :"+t.getTitle());
}
session.getTransaction().commit();
}
/**
* List每次默认发出sql查询
* @return @void
*/
@Test
public void testList1()
{
session.beginTransaction();
Query q1 = session.createQuery("from Topic t");
List<Topic> list1 = q1.list();
for(Topic t :list1)
{
log.debug("Topic :"+t);
}
Query q2 = session.createQuery("from Topic t");
List<Topic> list2 = q2.list();
for(Topic t :list2)
{
log.debug("Topic :"+t);
}
session.getTransaction().commit();
}
缓存 | 原理 | 生命周期 | 配置 | 方法 | 管理 |
一级缓存 | session级别的缓存 | session的生命周期 | 无 | ● get, ● load, ● iterate |
● evit(Object obj)
● clear()
● contains(Object obj)
● flush()
|
二级缓存 |
二级缓存也称为进程级的缓存,也可称为SessionFactory级的缓存(因为SessionFactory可以管理二级缓存)
二级缓存可以被所有的session共享,
二级缓存同session级缓存一样,只缓存实体对象,普通属性的查询不会缓存
二级缓存一般使用第三方的产品,如EHCache
| 二级缓存的生命周期和SessionFactory的生命周期一样,SessionFactory可以管理二级缓存 | ● jar包 ● ehcache.xml ● hibernate.cfg.xml
<
property name
=
"cache.use_second_level_cache"
>
true
</
property
>
<!-- 注意三者区别 -->
<!-- hibernte 3
<property name="cache.provider_class">
org.hibernate.cache.EhCacheRegionFactory
</property>-->
<!-- hibernte 4.2
<property name="cache.region.factory_class">
org.hibernate.cache。ehcache.EhCacheRegionFactory
</property>-->
<!-- hibernte 4.3.10 -->
<property name="cache.region.factory_class">
org.hibernate.cache.ehcache.EhCacheRegionFactory
</property>
● entity类
@Entity
@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Category
|
● load默认使用二级缓存,
● iterate默认使用二级缓存
● list默认向二级缓存中加数据,但是查询时候不使用
| ● evict ● 注意4.3.10版本放弃了evict,改用getCache()统一管理 |
查询缓存 | 查询缓存 key值是hql,value值是实体主键,主要作用是缓存普通属性查询。 | 当前关联的表发生修改,那么查询缓存生命周期结束 |
<!-- 打开查询缓存 -->
<property name="cache.use_query_cache">true</property>
| ●list ●iterator不起作用 | 无 |
/**
* 控制台输出:
* Hibernate:
select
category0_.id as id1_0_0_,
category0_.name as name2_0_0_
from
Category category0_
where
category0_.id=?
Category :com.liuhao.hibernate4.demo.query2.Category@98bbf6[id=1,name=c0]
Category :com.liuhao.hibernate4.demo.query2.Category@98bbf6[id=1,name=c0]
* @return @void
*/
@Test
public void testGet()
{
session.beginTransaction();
Category c1 = (Category) session.get(Category.class, 1);
Category c2 = (Category) session.get(Category.class, 1);
System.out.println("Category :"+c1);
System.out.println("Category :"+c2);
session.getTransaction().commit();
}
/**
* 控制台输出:
* Hibernate:
select
category0_.id as id1_0_0_,
category0_.name as name2_0_0_
from
Category category0_
where
category0_.id=?
Category :com.liuhao.hibernate4.demo.query2.Category@98bbf6[id=1,name=c0]
Category :com.liuhao.hibernate4.demo.query2.Category@98bbf6[id=1,name=c0]
* @return @void
*/
@Test
public void testLoad()
{
session.beginTransaction();
Category c1 = (Category) session.load(Category.class, 1);
Category c2 = (Category) session.load(Category.class, 1);
System.out.println("Category :"+c1);
System.out.println("Category :"+c2);
session.getTransaction().commit();
}
/**
* Hibernate:
select
category0_.id as col_0_0_
from
Category category0_
where
category0_.id=1
Hibernate:
select
category0_.id as col_0_0_
from
Category category0_
where
category0_.id=1
Hibernate:
select
category0_.id as id1_0_0_,
category0_.name as name2_0_0_
from
Category category0_
where
category0_.id=?
Category :com.liuhao.hibernate4.demo.query2.Category@1bbbafc[id=1,name=c0]
Category :com.liuhao.hibernate4.demo.query2.Category@1bbbafc[id=1,name=c0]
* @return @void
*/
@Test
public void testIterate()
{
session.beginTransaction();
Iterator c1 = (Iterator) session.createQuery("from Category where id = 1").iterate();
Iterator c2 = (Iterator) session.createQuery("from Category where id = 1").iterate();
while(c1.hasNext())
{
Category c = (Category) c1.next();
System.out.println("Category :"+c);
}
while(c2.hasNext())
{
Category c = (Category) c2.next();
System.out.println("Category :"+c);
}
session.getTransaction().commit();
}
@Test
public void testClear()
{
session.beginTransaction();
Iterator c1 = (Iterator) session.createQuery("from Category where id = 1").iterate();
Iterator c2 = (Iterator) session.createQuery("from Category where id = 1").iterate();
while(c1.hasNext())
{
Category c = (Category) c1.next();
System.out.println("Category :"+c);
}
while(c2.hasNext())
{
Category c = (Category) c2.next();
System.out.println("Category :"+c);
}
//清除session
session.clear();
Iterator c3 = (Iterator) session.createQuery("from Category where id = 1").iterate();
while(c3.hasNext())
{
Category c = (Category) c3.next();
System.out.println("Category :"+c);
}
session.getTransaction().commit();
}
@Test
public void testEvict()
{
session.beginTransaction();
Category c1 = (Category) session.load(Category.class, 1);
Category c2 = (Category) session.load(Category.class, 1);
System.out.println("Category :"+c1);
System.out.println("Category :"+c2);
//清除的是放入session的对象 不能是Query,Iterator
session.evict(c1);
session.evict(c2);
Category c3 = (Category) session.load(Category.class, 1);
System.out.println("Category3 :"+c3);
session.getTransaction().commit();
}
create or replace procadure UserUpdate(u_age in number) as
begin
update users set age=age+1 where age>u_age;
end;
Session session =SessionFactory.openSession();
Transaction tx =session.beginTransaction();
Connection conn=session.connection();
String str="{call UserUpdate(?)}";
CallableStatement cstmt= conn.prepareCall(str);
cstmt.setInt(1,0);
cstmt.executeUpdate();
tx.commit();
sessionFactory.evict(Customer.class, new Integer(1));
sessionFactory.evict(Customer.class);
sessionFactory.evictCollection("Customer.orders");
Cache cache = sfactory.getCache();
//清除所有
cache.evictAllRegions();
//cache.evictEntityRegion(Category.class);//清除指定类
//cache.evictEntity(Category.class,1);//清除指定类的指定数据
/*清除集合
cache.evictCollectionRegions();
cache.evictCollectionRegion(arg0);
cache.evictCollection(arg0, arg1);
*/
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<!--如果缓存中的对象存储超过指定的缓存数量的对象存储的磁盘地址-->
<diskStore path="D:/ehcache"/>
<!-- 默认cache:如果没有对应的特定区域的缓存,就使用默认缓存 -->
<defaultCache maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="false"/>
<!-- 指定区域cache:通过name指定,name对应到Hibernate中的区域名即可-->
<cache name="cn.javass.h3test.model.UserModel"
eternal="false"
maxElementsInMemory="100"
timeToIdleSeconds="1200"
timeToLiveSeconds="1200"
overflowToDisk="false">
</cache>
</ehcache>
Cache | Provider class | Type | Cluster Safe | Query Cache Supported |
Hashtable (not intended for production use) | org.hibernate.cache.HashtableCacheProvider | memory |
| yes |
EHCache | org.hibernate.cache.EhCacheProvider | memory, disk |
| yes |
OSCache | org.hibernate.cache.OSCacheProvider | memory, disk |
| yes |
SwarmCache | org.hibernate.cache.SwarmCacheProvider | clustered (ip multicast) | yes (clustered invalidation) |
|
JBoss TreeCache | org.hibernate.cache.TreeCacheProvider | clustered (ip multicast), transactional | yes (replication) | yes (clock sync req.) |
<!-- 二级缓存默认打开,这里只是显示打开一下 -->
<property name="cache.use_second_level_cache">true</property>
<!-- 注意3和4者区别 -->
<!-- hibernte 3
<property name="cache.provider_class">
org.hibernate.cache.EhCacheRegionFactory
</property>-->
<!-- hibernte 4.3.10 -->
<property name="cache.region.factory_class">
org.hibernate.cache.ehcache.EhCacheRegionFactory
</property>
@Entity
@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Category {
private int id;
private String name;
@Id
@GeneratedValue
public int getId() {
return id;
}
//set get...
}
//确保数据库中有标识符为1的FarmModel
FarmModel farm = (FarmModel) session.get(FarmModel.class, 1);
//如果修改将报错,只读缓存不允许修改
//farm.setName("aaa");
@Cache(usage =CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public SortedSet<Ticket> getTickets(){
return tickets;
}
@Test
public void testload()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session = sfactory.openSession();
session.beginTransaction();
Category c1 = (Category) session.load(Category.class,1);
System.out.println("Category :"+c1);
session.close();
//第二个session但是SessionFactory没有关闭
Session session2 = sfactory.openSession();
Category c2 = (Category) session2.load(Category.class,1);
System.out.println("Category :"+c2);
session2.close();
sfactory.close();
}
@Test
public void testiterate()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session = sfactory.openSession();
session.beginTransaction();
Query q1 = (Query) session.createQuery("from Category where name='c0'");
Iterator<?> iterator = q1.iterate();
while(iterator.hasNext())
{
Category c = (Category) iterator.next();
System.out.println("Category :"+c);
}
session.close();
//第二个session但是SessionFactory没有关闭
Session session2 = sfactory.openSession();
Query q2 = (Query) session2.createQuery("from Category where name='c0'");
Iterator<?> iterator2 = q2.iterate();
while(iterator2.hasNext())
{
Category c = (Category) iterator2.next();
System.out.println("Category :"+c);
}
session2.close();
sfactory.close();
}
@Test
public void testiterate_load() {
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session = sfactory.openSession();
session.beginTransaction();
Query q1 = (Query) session.createQuery("from Category where name='c0'");
Iterator<?> iterator = q1.iterate();
while (iterator.hasNext()) {
Category c = (Category) iterator.next();
System.out.println("Category :" + c);
}
session.close();
// 第二个session但是SessionFactory没有关闭
Session session2 = sfactory.openSession();
Category c2 = (Category) session2.load(Category.class, 1);
System.out.println("Category :" + c2);
session2.close();
sfactory.close();
}
/**
*
* list 只存不取
* @return @void
*/
@SuppressWarnings("unchecked")
@Test
public void testlist_load() {
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session = sfactory.openSession();
session.beginTransaction();
Query q1 = (Query) session.createQuery("from Category where name='c0'");
for (Category c : (List<Category>)q1.list()) {
System.out.println("Category :" + c);
}
session.close();
// 第二个session但是SessionFactory没有关闭
Session session2 = sfactory.openSession();
Category c2 = (Category) session2.load(Category.class, 1);
System.out.println("Category :" + c2);
session2.close();
sfactory.close();
}
@Test
public void testEvict()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session = sfactory.openSession();
session.beginTransaction();
Category c1 = (Category) session.load(Category.class,1);
System.out.println("Category :"+c1);
session.close();
//4.3中evict过时,使用getCache
//sfactory.evict(Category.class);
Cache cache = sfactory.getCache();
//清除所有
cache.evictAllRegions();
//cache.evictEntityRegion(Category.class);//清除指定类
//cache.evictEntity(Category.class,1);//清除指定类的指定数据
/*清除集合
cache.evictCollectionRegions();
cache.evictCollectionRegion(arg0);
cache.evictCollection(arg0, arg1);
*/
//第二个session但是SessionFactory没有关闭
Session session2 = sfactory.openSession();
Category c2 = (Category) session2.load(Category.class,1);
System.out.println("Category :"+c2);
session2.close();
sfactory.close();
}
CacheMode参数用于控制具体的Session如何与二级缓存进行交互。
CacheMode.NORMAL - 从二级缓存中读、写数据。
CacheMode.IGNORE- session不会与二级缓存交互。
CacheMode.GET - 从二级缓存中读取数据,仅在数据更新时对二级缓存写数据。
CacheMode.PUT - 仅向二级缓存写数据,但不从二级缓存中读数据。
CacheMode.REFRESH - 仅向二级缓存写数据,但不从二级缓存中读数据。通过hibernate.cache.use_minimal_puts(是否优化二级缓存操作,最小化缓存写入操作(适用与集群缓存))的设置,强制二级缓存从数据库中读取数据,刷新缓存内容。
如若需要查看二级缓存或查询缓存区域的内容,你可以使用统计(Statistics) API。
Map cacheEntries = sessionFactory.getStatistics()
.getSecondLevelCacheStatistics(regionName)
.getEntries();
此时,你必须手工打开统计选项。可选的,你可以让Hibernate更人工可读的方式维护缓存内容。
hibernate.generate_statistics true
hibernate.cache.use_structured_entries true
/**
* 从二级缓存中读取数据,仅在数据更新时对二级缓存写数据。
* @return @void
*/
@Test
public void testMutual_GET()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session1 = sfactory.openSession();
session1.setCacheMode(CacheMode.GET);
Category c1 = (Category) session1.load(Category.class, 1);
System.out.println("Category :"+c1);
session1.close();
System.out.println("-----------------------");
long count = sfactory.getStatistics()
.getSecondLevelCachePutCount();
System.out.println("Cache : "+count);
Session session2 = sfactory.openSession();
//不能取 所有两条sql
Category c2 = (Category) session2.load(Category.class, 1);
System.out.println("Category :"+c2);
session2.close();
sfactory.close();
}
/**
* 仅向二级缓存写数据,但不从二级缓存中读数据。
* @return @void
*/
@Test
public void testMutual_PUT()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session1 = sfactory.openSession();
session1.setCacheMode(CacheMode.PUT);
Category c1 = (Category) session1.load(Category.class, 1);
System.out.println("Category :"+c1);
session1.close();
System.out.println("-----------------------");
long count = sfactory.getStatistics()
.getSecondLevelCachePutCount();
System.out.println("Cache : "+count);
Session session2 = sfactory.openSession();
//一条sql 二级缓存有 且能取
Category c2 = (Category) session2.load(Category.class, 1);
System.out.println("Category :"+c2);
session2.close();
sfactory.close();
}
/**
* 仅向二级缓存写数据,但不从二级缓存中读数据。
* 通过hibernate.cache.use_minimal_puts
* (是否优化二级缓存操作,最小化缓存写入操作(适用与集群缓存))的设置,
* 强制二级缓存从数据库中读取数据,刷新缓存内容。
* @return @void
*/
@Test
public void testMutual_REFRESH()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session1 = sfactory.openSession();
Category c1 = (Category) session1.load(Category.class, 1);
System.out.println("Category :"+c1);
session1.close();
System.out.println("-----------------------");
long count = sfactory.getStatistics()
.getSecondLevelCachePutCount();
System.out.println("Cache : "+count);
Session session2 = sfactory.openSession();
session2.setCacheMode(CacheMode.REFRESH);
//两条sql 二级缓存有 但不能取
Category c2 = (Category) session2.load(Category.class, 1);
System.out.println("Category :"+c2);
session2.close();
sfactory.close();
}
/**
* session与二级缓存之间没有交互
* @return @void
*/
@Test
public void testMutual_IGONORE()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
Session session1 = sfactory.openSession();
session1.setCacheMode(CacheMode.IGNORE);
Category c1 = (Category) session1.load(Category.class, 1);
System.out.println("Category :"+c1);
session1.close();
System.out.println("-----------------------");
long count = sfactory.getStatistics()
.getSecondLevelCachePutCount();
System.out.println("Cache : "+count);
Session session2 = sfactory.openSession();
//两条sql 二级缓存有 但不能取
Category c2 = (Category) session2.load(Category.class, 1);
System.out.println("Category :"+c2);
session2.close();
sfactory.close();
}
<!-- 打开查询缓存 -->
<property name="cache.use_query_cache">true</property>
<!-- 二级缓存默认打开,这里只是显示打开一下 -->
<property name="cache.use_second_level_cache">true</property>
<!-- 注意3和4区别 -->
<!-- hibernte 3
<property name="cache.provider_class">
org.hibernate.cache.EhCacheRegionFactory
</property>
-->
<!-- hibernte 4.3.10 -->
<property name="cache.region.factory_class">
org.hibernate.cache.ehcache.EhCacheRegionFactory
</property>
@Entity
@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Category
Query q = session.createQuery("from Category where name = 'c0'");
//手动打开查询缓存
q.setCacheable(true);
public void testquerylist(SessionFactory sfactory)
{
Session session = sfactory.openSession();
session.beginTransaction();
Query q = session.createQuery("from Category where name = 'c0'");
q.setCacheable(true);
List<Category> list = (List<Category>)q.list();
for(Category c : list)
{
System.out.println("Category : "+c);
}
session.getTransaction().commit();
session.close();
}
public void testqueryiterator(SessionFactory sfactory)
{
Session session = sfactory.openSession();
session.beginTransaction();
Query q = session.createQuery("from Category where name = 'c0'");
q.setCacheable(true);
Iterator iterate = q.iterate();
while(iterate.hasNext())
{
Category c = (Category) iterate.next();
System.out.println("Category : "+c);
}
session.getTransaction().commit();
session.close();
}
/**
* 第一次list 查询
Hibernate:
select
category0_.id as id1_0_,
category0_.name as name2_0_
from
Category category0_
where
category0_.name='c0'
Category : com.liuhao.hibernate4.demo.query2.Category@17b2b2[id=1,name=c0]
第二次list 查询
Hibernate:
select
category0_.id as id1_0_0_,
category0_.name as name2_0_0_
from
Category category0_
where
category0_.id=?
Category : com.liuhao.hibernate4.demo.query2.Category@43da1b[id=1,name=c0]
* 第一次会将发出sql,然后将满足条件的实体主键放入查询缓存中,
* 查询缓存中key是hql,value是查询到的实体主键
* 第二次发出sql时,list先到查询缓存中查询,获取满足条件的id然后到数据库获取实体属性,
* 如果没有直接到数据库查询
* @return @void
*/
@Test
public void testQuerylist_list()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
System.out.println("第一次list 查询");
testquerylist(sfactory);
System.out.println("第一次list 查询");
testquerylist(sfactory);
}
/**
* 第一次iterator 查询
Hibernate:
select
category0_.id as col_0_0_
from
Category category0_
where
category0_.name='c0'
Hibernate:
select
category0_.id as id1_0_0_,
category0_.name as name2_0_0_
from
Category category0_
where
category0_.id=?
Category : com.liuhao.hibernate4.demo.query2.Category@1c4a5ec[id=1,name=c0]
第二次iterator 查询
Hibernate:
select
category0_.id as col_0_0_
from
Category category0_
where
category0_.name='c0'
Hibernate:
select
category0_.id as id1_0_0_,
category0_.name as name2_0_0_
from
Category category0_
where
category0_.id=?
Category : com.liuhao.hibernate4.demo.query2.Category@21447f[id=1,name=c0]
iterator每次都是查询满足条件的实体主键,
然后到数据库中获取对应主键的实体属性
* @return @void
*/
@Test
public void testQueryiterate_iterate()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
System.out.println("第一次iterator 查询");
testqueryiterator(sfactory);
System.out.println("第一次iterator 查询");
testqueryiterator(sfactory);
}
/**
* 第一次list 查询
Hibernate:
select
category0_.id as id1_0_,
category0_.name as name2_0_
from
Category category0_
where
category0_.name='c0'
Category : com.liuhao.hibernate4.demo.query2.Category@17b2b2[id=1,name=c0]
第二次iterator 查询
Hibernate:
select
category0_.id as col_0_0_
from
Category category0_
where
category0_.name='c0'
Hibernate:
select
category0_.id as id1_0_0_,
category0_.name as name2_0_0_
from
Category category0_
where
category0_.id=?
Category : com.liuhao.hibernate4.demo.query2.Category@37165f[id=1,name=c0]
list 将查询到的实体主键放入查询缓存中,
literator对查询缓存的策略是不存,不取
* @return @void
*/
@Test
public void testQuerylist_iterate()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
System.out.println("第一次list 查询");
testquerylist(sfactory);
System.out.println("第二次iterator 查询");
testqueryiterator(sfactory);
}
/**
* 第一次iterator 查询
Hibernate:
select
category0_.id as col_0_0_
from
Category category0_
where
category0_.name='c0'
Hibernate:
select
category0_.id as id1_0_0_,
category0_.name as name2_0_0_
from
Category category0_
where
category0_.id=?
Category : com.liuhao.hibernate4.demo.query2.Category@1c4a5ec[id=1,name=c0]
第二次list 查询
Hibernate:
select
category0_.id as id1_0_,
category0_.name as name2_0_
from
Category category0_
where
category0_.name='c0'
Category : com.liuhao.hibernate4.demo.query2.Category@1a1ff9[id=1,name=c0]
* @return @void
*/
@Test
public void testQueryiterate_list()
{
SessionFactory sfactory = HibernateUtil.getSessionFactory();
System.out.println("第一次iterator 查询");
testqueryiterator(sfactory);
System.out.println("第二次list 查询");
testquerylist(sfactory);
}