Hibernate 配置详解(8)
hibernate.generate_statistics
这个配置大家应该都很熟悉,用于开启Hibernate统计信息,便于对Hibernate相关性能调试提供数据依据。在开发过程当中,可以把这个选项设置为true。
下面主要再来看看Statistics的一些用法:
首先看看Statistics的体系结构:可以通过SessionFactory.getStatistics()方法得到Statistics对象,然后就可以通过Statistics得到相关的细节的统计信息:
其中:
Statistics:针对某一个SessionFactory的统计信息,是一个比较笼统的信息统计。该对象还有一些重要的方法是用于得到针对某一些具体特性的统计信息对象。
EntityStatistics:针对某一个具体实体类型的统计信息,可以统计到该实体类型的insert,load,update,get,乐观锁失败等操作个数;
CollectionStatistics:针对某一个实体集合关系(比如one2many,many2many)的统计信息;可以统计到这个集合关系的加载次数,发送的SQL次数,删除和修改次数;
QueryStatistics:针对某一个具体的HQL/SQL查询的统计信息;可以统计到这个HQL/SQL的查询次数,查询缓存情况,查询时间等信息;
SecondLevelCacheStatistics:针对某一个二级缓存区域(region),得到该缓存区域的命中数,缓存对象个数,内存占用大小等信息;
NaturalIdCacheStatistics:针对某一个二级缓存区域(region),得到该缓存区域对自然主键(naturalId)缓存的存放个数,丢失个数,执行时间,存放数据个数等信息。
对于EntityStatistics、CollectionStatistics、QueryStatistics、SecondLevelCacheStatistics和NaturalIdCacheStatistics这几个对象来说,要获得具体的对象实例,都需要通过Statistics对象上面的方法来获取,下面分别举例说明:
比如对于Employee和Department对象来说,假设是一个双向many2one/one2many关系,准备数据代码:
@Before
public void save() {
Department d = new Department();
d.setName("d1");
Department d2 = new Department();
d2.setName("d2");
Department d3 = new Department();
d3.setName("d3");
Employee e = new Employee();
e.setDept(d);
Employee e2 = new Employee();
e2.setDept(d);
Employee e3 = new Employee();
e3.setDept(d2);
Employee e4 = new Employee();
e4.setDept(d2);
Employee e5 = new Employee();
e5.setDept(d2);
Session session = HibernateUtil.getInstance().getSession();
session.beginTransaction();
session.save(d);
session.save(d2);
session.save(d3);
session.save(e);
session.save(e2);
session.save(e3);
session.save(e4);
session.save(e5);
session.getTransaction().commit();
session.close();
}
分别保存了3个dept和5个emp,下面分别来看这几个特殊的统计对象:
1,EntityStatistics:
@Test
public void testStatics() {
Statistics st = HibernateUtil.getInstance().getSf().getStatistics();
EntityStatistics es = st
.getEntityStatistics("cd.itcast.hibernate.day2.many2one.Department");
EntityStatistics es2 = st
.getEntityStatistics("cd.itcast.hibernate.day2.many2one.Employee");
System.out.println(es);
System.out.println(es2);
}
控制台输出:
EntityStatistics[loadCount=0,updateCount=0,insertCount=3,deleteCount=0,fetchCount=0,optimisticLockFailureCount=0]
EntityStatistics[loadCount=0,updateCount=0,insertCount=5,deleteCount=0,fetchCount=0,optimisticLockFailureCount=0]
简单说明:
1,通过Statistics对象的getEntityStatistics(String entityName)得到对应Entity的实体统计信息,如果实体在映射的时候配置了entityName,则直接使用该entityName(特别对于动态模型),如果实体没有单独配置entityName,则就是类的全限定名。当然,假如我们在做一个Hibernate监控应用的话,我们更多的情况是使用Statistics对象的getEntityNames()来得到所有的Hibernate管理的EntityName。
2,在EntityStatistics中,可以得到的具体信息有:
getDeleteCount:该实体删除个数
getInsertCount:该实体保存个数
getLoadCount:该实体加载次数(get/load总次数)
getUpdateCount:该实体更新次数
getFetchCount:该实体到数据库中查询的次数
getOptimisticFailureCount:该实体乐观锁失败个数
2,CollectionStatistics:
@Test
public void testStatics2() {
Session session = HibernateUtil.getInstance().getSession();
List<Department> depts = session.createQuery("FROM Department").list();
for (Department d : depts) {
System.out.println(d.getEmps());
}
session.close();
Statistics st = HibernateUtil.getInstance().getSf().getStatistics();
CollectionStatistics cs = st
.getCollectionStatistics("cd.itcast.hibernate.day2.many2one.Department.emps");
System.out.println(cs);
}
控制台输出:
CollectionStatistics[loadCount=3,fetchCount=3,recreateCount=3,removeCount=0,updateCount=0]
简单说明:
1,通过Statistics对象的getCollectionStatistics(String role)得到对应Entity的集合关系统计信息,需要根据具体的关系来得到。关系的意思很简单,就是表明类的全限定名+“.”+表关系的属性名(简单理解,就是那个set/list/map/bag配置的name名字)。当然,假如我们在做一个Hibernate监控应用的话,我们更多的情况是使用Statistics对象的getCollectionRoleNames()来得到所有的Hibernate管理的roleName。
2,在CollectionStatistics对象上,可以得到的具体信息有:
getLoadCount:得到这个关系加载的次数
getFetchCount:得到这个关系到数据库获取数据的次数
getRecreateCount:创建集合的次数
getRemoveCount:集合中有元素删除的次数
getUpdateCount:集合修改(即集合中数据增加)的次数
3,在上面的输出中,很明显能看到LoadCount和FetchCount相等,要提高性能,很明显需要减少LoadCount和FetchCount数量,那么就可以通过两种方式,第一种就是设置batch-fetch来减少FetchCount;第二种就是添加集合二级缓存减少LoadCount:
<collection-cache usage="read-write" collection="cd.itcast.hibernate.day2.many2one.Department.emps"/>
3,QueryStatistics:
@Test
public void testStatics3() {
Session session = HibernateUtil.getInstance().getSession();
session.createQuery("FROM Department").list();
session.createQuery("FROM Department").list();
session.createQuery("FROM Department").list();
session.createSQLQuery("SELECT * FROM DEPARTMENT").list();
List<Employee> es = session.createQuery("FROM Employee").list();
for (Employee e : es) {
e.getDept().getEmps().size();
}
session.close();
Statistics st = HibernateUtil.getInstance().getSf().getStatistics();
String[] queries = st.getQueries();
for (String q : queries) {
System.out.println(q);
QueryStatistics qs = st.getQueryStatistics(q);
System.out.println(qs);
}
}
控制台输出:
FROM Employee
QueryStatistics[cacheHitCount=0,cacheMissCount=0,cachePutCount=0,executionCount=1,executionRowCount=5,executionAvgTime=4,executionMaxTime=4,executionMinTime=4]
FROM Department
QueryStatistics[cacheHitCount=0,cacheMissCount=0,cachePutCount=0,executionCount=3,executionRowCount=9,executionAvgTime=8,executionMaxTime=23,executionMinTime=1]
SELECT * FROM DEPARTMENT
QueryStatistics[cacheHitCount=0,cacheMissCount=0,cachePutCount=0,executionCount=1,executionRowCount=3,executionAvgTime=8,executionMaxTime=8,executionMinTime=8]
简单说明:
1,通过Statistics对象的getQueryStatistics(String query)得到对应查询的统计信息,需要根据具体的查询语句来得到。当然,假如我们在做一个Hibernate监控应用的话,我们更多的情况是使用Statistics对象的getQueries()方法来得到执行到统计时刻在Hibernate中执行的所有查询。
2,注意,只有createQuery(即HQL)、createNamedQuery和createSQLQuery(即SQL)执行的查询才会在这个统计信息中反映出来,使用createCriteria或hibernate自动的延迟加载等查询是不会在这个统计信息中反映出来。
3,在QueryStatistics对象上面能够得到的统计信息有:
getExecutionCount:该查询执行的次数
getCacheHitCount:该查询在查询缓存中命中数量
getCachePutCount:该查询在查询缓存中存放的次数
getCacheMissCount:该查询在查询缓存中丢失的次数
getExecutionRowCount:该查询一共返回的ResultSet行数
getExecutionAvgTime:该查询执行的平均时间(ms)
getExecutionMaxTime:该查询执行的最长时间(ms)
getExecutionMinTime:该查询执行的最短时间(ms)
4,要提高查询性能,就是要想办法提高查询缓存命中率(CacheHitCount/ExecutionCount)和提高平均查询时间(ExecutionAvgTime),并且,如果CachePutCount过大,那么也说明该查询不适合缓存。
4,SecondLevelCacheStatistics
@Test
public void testStatistics4() {
Statistics st = HibernateUtil.getInstance().getSf().getStatistics();
String[] regions = st.getSecondLevelCacheRegionNames();
for (String region : regions) {
SecondLevelCacheStatistics scs = st
.getSecondLevelCacheStatistics(region);
System.out.println(scs);
}
}
控制台输出:
itcast.cd.itcast.hibernate.day2.many2one.Department.emps SecondLevelCacheStatistics[hitCount=0,missCount=0,putCount=0,elementCountInMemory=3,elementCountOnDisk=0,sizeInMemory=6081]
itcast.EMP SecondLevelCacheStatistics[hitCount=0,missCount=0,putCount=0,elementCountInMemory=0,elementCountOnDisk=0,sizeInMemory=0]
简单说明:
1,通过Statistics对象的getSecondLevelCacheStatistics(String regionName)得到对应缓存区域(region)的统计信息,需要根据具体的缓存区域名称来得到。当然,假如我们在做一个Hibernate监控应用的话,我们更多的情况是使用Statistics对象的getSecondLevelCacheRegionNames()方法来得到Hibernate中接入的所有缓存区域。
2,SecondLevelCacheStatistics上的统计信息:
getHitCount:得到该区域二级缓存命中次数
getMissCount:得到该区域二级缓存丢失次数
getPutCount:得到该区域二级缓存存放次数
getElementCountOnDisk:得到该区域二级缓存在磁盘上面的元素个数(如果允许了overFlowToDisk)
getSizeInMemory:得到该区域二级缓存在内存中的占用大小(byte)
Map getEntries():可以得到这个区域二级缓存中缓存的实体(注意这个实体不是真正的Employee或者Department对象,而是AbstractReadWriteEhcacheAccessStrategy.Lock对象,如果要得到更易读的缓存对象,需要设置hibernate.cache.use_structured_entries,这个配置后面会介绍)。
NaturalIdCacheStatistics
NaturalId代表自然主键,有别于代理主键<id>;在开发中使用的较少。要使用自然主键,需要修改一下Department的映射文件:
<class name="Department">
<cache usage="read-write" region="DEPT"/>
<id name="id">
<generator class="native" />
</id>
<natural-id>
<property name="name" />
</natural-id>
<set name="emps" lazy="extra" inverse="true">
<key column="DEPT_ID" />
<one-to-many class="Employee" />
</set>
</class>
注意一点的就是,natural-id是额外的一个作为自然主键的列,他必须和id同时存在。Hibernate会为标记为自然主键的属性或多个属性添加UNIQUE约束。
要使用NaturalId,主要是在查询的时候:
@Test
public void testStatistics5() {
Session session = HibernateUtil.getInstance().getSession();
session.createCriteria(Department.class)
.add(Restrictions.naturalId().set("name", "d1"))
.setCacheable(true).setCacheRegion("EMP").uniqueResult();
session.close();
session = HibernateUtil.getInstance().getSession();
session.byNaturalId(Department.class).using("name", "d1").load();
session.close();
Statistics st = HibernateUtil.getInstance().getSf().getStatistics();
String[] regions = st.getSecondLevelCacheRegionNames();
for (String region : regions) {
NaturalIdCacheStatistics ncs = st
.getNaturalIdCacheStatistics(region);
System.out.println(ncs);
}
}
简单解释一下:
1,要使用自然主键查询,一般有两种方式,一种方式是使用session新提供的byNaturalId方法,该方法需要传入查询对象的类型,并通过using(String propertyName,Object value)来设置要查询的自然主键属性及其值,然后再通过load()方法(立刻查询)或者byReference()方法(延迟加载)来完成对象的查询;第二种方式是通过createCriteria的Restrictions.naturalId约束来查询。
2,自然主键查询一般需要生成2条SQL:
SELECT id FROM DEPARTMENT WHERE name = ?
SELECT * FROM DEPARTMENT WHERE id = ?
即首先查询出符合自然主键的对象的ID,再通过得到的id去load对象。所以,一般情况下,使用自然主键查询对象,都需要开启二级缓存。
3,来看下输出:
NaturalIdCacheStatistics[hitCount=0,missCount=0,putCount=0,executionCount=0,executionAvgTime=0,executionMinTime=9223372036854775807,executionMaxTime=0,elementCountInMemory=1,elementCountOnDisk=0,sizeInMemory=2089]
注意就是在naturalIdCacheStatistics中保存的是NaturalId和对应的对象的ID值。
了解了以上这些内容,要做一个简单的全面监控Hibernate的模块就是很简单的事情了。
Hibernate 配置详解(8)的更多相关文章
- Hibernate 配置详解(9)
hibernate.cache.use_structured_entries Hibernate文档上介绍,该属性是用于把对象以一种更易读的方式放到二级缓存中,这样,在对二级缓存进行监控的时候就更容易 ...
- Hibernate 配置详解(2)
6) hibernate.session_factory_name: 配置一个JNDI名称,通过Configuration对象创建的SessionFactory会绑定到JNDI下该名称中.一般名字格式 ...
- Hibernate 配置详解(5)
9) hibernate.batch_fetch_style: 该配置是hibernate4.2.0新添加的,使用这个设置可以配置hibernate在做batch-fetch的时候,生成SQL的策略. ...
- Hibernate 配置详解(12) 补充
hibernate.hbm2ddl.import_files_sql_extractor 这个配置项用于补充这篇文章: http://blog.csdn.net/stefwu/article/deta ...
- Hibernate 配置详解(12) 其实我也不想用这么土的名字
hibernate.hbm2ddl.import_files 这个配置用于在hibernate根据映射文件执行DDL之前,如果我们自己设置了要事先运行的SQL文件,hibernate就会先执行这些SQ ...
- Hibernate 配置详解(7)
hibernate.order_updates: Hibernate文档中提到,该配置用于在刷新一级缓存,提交UPDATE的时候,按照每类对象的主键顺序排序后再提交,可以在高并发情况下减少事务死锁的可 ...
- Hibernate 配置详解(11)
hibernate.session_factory_name_is_jndi 配置hibernate.cfg.xml中SessionFactory的name属性是否作为JNDI名称绑定.默认是true ...
- hibernate二级缓存ehcache hibernate配置详解
<!-----------------hibernate二级缓存ehcache------------------------->hibernate配置 <prop key=&quo ...
- Hibernate配置详解
<!--标准的XML文件的起始行,version='1.0'表明XML的版本,encoding='gb2312'表明XML文件的编码方式--> <?xml version='1.0' ...
随机推荐
- idea
一. 常用快捷键 搜索class Ctrl+N 搜索文件 Ctrl+Alt+N 当前窗口查找/全工程查找 Ctrl+F/Ctrl+Shift+F,F3/Shift+F3前后移动 上/下一个位置 Ctr ...
- 【转】android cts failed items
原文网址:http://blog.csdn.net/linsa0517/article/details/19031479 Fail的一些修改 1.直接设置问题 estUnknownSourcesO ...
- 福建省队集训被虐记——DAY4
啊啊啊啊啊啊第四天考的是我最不擅长的图论--整个人都斯巴达了 //另外不得不吐槽下午的上课讲的都是网络流--难道是出题人觉得图论里除了网络流以外的其他算法都没有人权图样图森破? 愚蠢的算法(clums ...
- 安卓Menu键的问题
近期开发中有须要Menu键,结果发现了一个非常尴尬的问题.我的測试机上有Menu键.可是測试平板上没有,队友的測试机上竟然也没有Menu键.这着实有些尴尬... 上网谷歌之后才发现问题所在: 仅仅有在 ...
- Android内存泄漏监测(MAT)及解决办法
http://ttlnews.blogspot.com/2010/01/attacking-memory-problems-on-android.html 这篇文章是2010年1月份写的,其中有些已经 ...
- [Firmware Warn]: GHES: Failed to read error status block address for hardware error source
Firmware Warn 问题描述: 系统版本:Ubuntu 12.04 LTS. 系统启动后dmesg打印大量Firmware Warn告警信息到syslog文件中.信息如下: [Firmware ...
- [core java学习笔记][第十章部署应用程序]
第10章 部署应用程序和applet jar文件 Java Web Start 10.1 jar文件 jar文件就是一个压缩了类,图像和声音的ZIP压缩文件 创建一个新的JAR文件应该使用的常见命令格 ...
- 基于ADODBX对数据库的CURD
学asp.net也有一个多星期了,之前对这个一无所知,也不知道怎么去找一些相关的资料去学习,不懂了就问问别人这个怎么做,那个怎么写,要不是有jsp和php的基础,估计还得弄上好长的时间来学习.记录一下 ...
- Glide的加载图片的帮助类,用来把图片圆角或者改成圆形图片
Glide虽然非常好用但是没找到把图片圆角的方法,所以百度了一个非常不错的加载类自己实现圆角图 感谢原文章作者:http://blog.csdn.net/weidongjian/article/det ...
- IBM SPSS Modeler 预测建模基础(一)
1.搜索下载IBM SPSS Modeler 14.1 32位 及 IBM SPSS Modeler 14.1 注册文件(破解布丁): 2.下载train.csv 及 test.csv: train. ...