标签:evel ber sql数据库 max mil 推荐 show 范围 abstract
Hibernate是好多的传统项目的首选,因其自动化程度高,使用书写方便,深得好多的传统项目的青睐,估计您也是使用的Hibernate吧, 既然使用了,那么您对他很熟吗? 我就问他俩问题: 1.Hibernate底层是怎么实现的?2.Hibernate的二级缓存用过吗? 估计大部分人都会懵逼特斯拉。不要紧,今天这个文章会让你对Hibernate刮目相看!
Hibernate的核心配置文件
在src下创建一个hibernate.cfg.xml
以下为配置文件的详情。
<?xml version="1.0" encoding="utf-8"?>
<hibernate-configuration>
<session-factory>
<!-- 必须去配置的属性 -->
<!-- 配置数据库连接的基本信息: -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///hibernate3_day01</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123</property>
<!-- Hibernate的方言 -->
<!--
为实现HQL语句向不同数据库的SQL语句转换时,解决不同数据库之间的差异而制定的一套”规范”。
举例来说,我们在MySQL数据库里进行分页查询,只需使用limit关键字就可以了;而标准SQL并不支持limit关键字,例如Oracle则需要使用行内视图的方式来进行分页。同样的应用程序,当我们在不同数据库之间迁移时,底层数据库的访问细节会发生改变,而Hibernate也为这种改变做好了准备,现在我们需要做的是:告诉Hibernate应用程序的底层即将使用哪种数据库——这就是Hibernate方言。为了适配不同的数据库的规范而设计的适配方式。每一种数据库的方言方式都不一样。
-->
<!-- 生成底层SQL不同的 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 以下是可选的属性 可以使用也可以不适用 -->
<!-- 显示SQL -->
<property name="hibernate.show_sql">true</property>
<!-- 格式化SQL -->
<property name="hibernate.format_sql">true</property>
<!-- hbm:映射 to DDL: create drop alter -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 通知Hibernate加载那些映射文件(配置hibernate与数据库的字段的映射文件 ) -->
<mapping resource="cn/itcast/hibernate3/demo1/Customer.hbm.xml"/>
<!--可选的配置:
hibernate.show_sql true 在控制台上输出SQL语句
hibernate.format_sql true 格式化控制台输出的SQL语句
hibernate.connection.autocommit true 事务是否自动提交
hibernate.hbm2ddl.auto create/create-drop/update/validate
* create :每次执行的时候,创建一个新的表.(如果以前有该表,将该表删除重新创建.) 一般测试的时候的使用.
* create-drop :每次执行的时候,创建一个新的表,程序执行结束后将这个表,删除掉了. 一般测试的时候使用.
* update :如果数据库中没有表,创建一个新的表,如果有了,直接使用这个表.可以更新表的结构.
* validate :会使用原有的表.完成校验.校验映射文件与表中配置的字段是否一致.不一致报错.-->
<!--在Hibernate中使用c3p0连接池:
* 引入c3p0的jar包
* 在核心配置中添加一段配置:
<!-- C3P0连接池设定-->
<!-- 使用c3po连接池 配置连接池提供的供应商-->
<!--
<propertyname="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider </property>
<!--在连接池中可用的数据库连接的最少数目 -->
<!--<property name="c3p0.min_size">5</property>
<!--在连接池中所有数据库连接的最大数目 -->
<!--<property name="c3p0.max_size">20</property>
<!--设定数据库连接的过期时间,以秒为单位,
如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
<!--<property name="c3p0.timeout">120</property>
<!--每3000秒检查所有连接池中的空闲连接 以秒为单位-->
<!--<property name="c3p0.idle_test_period">3000</property>-->
</session-factory>
</hibernate-configuration>
接下来再说说hibernate的缓存机制:
1. 使用一级缓存的目的是为了减少对数据库的访问次数,从而提升hibernate的执行效率;(当执行一次查询操作的时候,执行第二次查询操作,先检查缓存中是否有数据,如果有数据就不查询数据库,直接从缓存中获取数据);
1.2:Hibernate中的一级缓存,也叫做session的缓存,它可以在session范围内减少数据库的访问次数,只在session范围内有效,session关闭,一级缓存失败;
1.3:一级缓存的特点,只在session范围有效,作用时间短,效果不是特别明显,在短时间内多次操作数据库,效果比较明显。
1.4:当调用session的save/saveOrUpdate/get/load/list/iterator方法的时候,都会把对象放入session缓存中;
1.5:session的缓存是由hibernate维护的,用户不能操作缓存内容;如果想操作缓存内容,必须通过hibernate提供的evict/clear方法操作
1.6:缓存相关的方法(在什么情况下使用上面方法呢?批量操作情况下使用,如Session.flush();先与数据库同步,Session.clear();再清空一级缓存内容):
session.flush();让一级缓存与数据库同步;
session.evict();清空一级缓存中指定的对象;
session.clear();清空一级缓存中所有的对象;
1.7:面试题,不同的session是否会共享缓存数据?
答:不会哦~~~
1.8:list和iterator的区别?
(1)list查询:
答: 一次性把所有的记录都查询出来了;会放入缓存,不会从缓存中取数据;
(2)iterate(N+1次查询):
答: N表示所有的记录总数,即会发送一条语句查询所有的记录的主键,这是第一条查询语句,再根据每一个主键取数据库查询,这是根据第一次查询的条数进行N次查询操作;会放入缓存,也会从缓存中取出数据;
2:Hibernate的懒加载:
2.1:懒加载概念:当用到数据的时候才向数据库查询,这就是hibernate的懒加载特性。
使用懒加载的目的,是提高程序执行效率。
2.2:查询操作:get()方法/load()方法
(1)get()方法,及时加载。及时查询操作;只要调用get方法立刻向数据库查询。
(2)load()方法,默认懒加载,即在使用数据的时候,才向数据库发送查询的sql语句。session关闭以后,不可以使用懒加载。
复制代码
#懒加载默认为true,即为懒加载,可以改为非懒加载。即lazy="false"
#lazy="false" 关闭懒加载
#lazy="true"使用懒加载
#lazy="extra"在真正使用数据的时候才向数据库发送查询的sql语句。集合属性懒加载的时候提升效率。如果调用集合的size()/isEmpty()方法只是统计,不真正查询数据。
<class name="类名称" table="数据表名称" lazy="false">
......
</class>
2.3:懒加载异常:
Session关闭后,不能使用懒加载数据,如果session关闭后,使用懒加载数据报错如:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.
........................
如何解决session关闭后不能使用懒加载加载数据的问题:
方式一:可以先在关闭session之前使用一下数据,这样关闭以后就可以使用此数据了。如Dept.getDeptName();
方式二(推荐):强迫代理对象初始化操作:Hibernate.initialize(对象);
方式三:关闭懒加载(lazy="false");
方式四(推荐):在使用数据之后再关闭session;
3:二级缓存:
Hibernate提供的缓存
有一级缓存、二级缓存。 目的是为了减少对数据库的访问次数,提升程序执行效率!
一级缓存:
基于Session的缓存,缓存内容只在当前session有效,session关闭,缓存内容失效!
特点:
作用范围较小! 缓存的事件短。
缓存效果不明显。
二级缓存:
Hibernate提供了基于应用程序级别的缓存即为二级缓存,可以跨多个session,即不同的session都可以访问缓存数据。 这个缓存也叫二级缓存。
Hibernate提供的二级缓存有默认的实现,且是一种可插配的缓存框架!如果用户想用二级缓存,只需要在hibernate.cfg.xml中配置即可; 不想用,直接移除,不影响代码。
如果用户觉得hibernate提供的框架框架不好用,自己可以换其他的缓存框架或自己实现缓存框架都可以。
3.2:查看hibernate.properties配置文件,二级缓存如何配置?
相关配置的文件:
### Second-level Cache ###
#hibernate.cache.use_second_level_cache false【二级缓存默认不开启,需要手动开启】
#hibernate.cache.use_query_cache true 【开启查询缓存】
## choose a cache implementation 【二级缓存框架的实现】
#hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider
hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider 默认实现
#hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider
二级缓存配置:
<!--****************** 【二级缓存配置】****************** -->
<!-- a. 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- b. 指定使用哪一个缓存框架(默认提供的) -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
<!-- 开启查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>
<!-- c. 指定哪一些类,需要加入二级缓存 -->
<class-cache usage="read-write" class="com.bie.lesson11.Dept"/>
<class-cache usage="read-only" class="com.bie.lesson11.Employee"/>
<!-- 集合缓存[集合缓存的元素对象,也加加入二级缓存] -->
<collection-cache usage="read-write" collection="com.bie.lesson11.Dept.emps"/>
缓存策略:
<class-cache usage="read-only"/> 放入二级缓存的对象,只读;
<class-cache usage="nonstrict-read-write"/> 非严格的读写
<class-cache usage="read-write"/> 读写; 放入二级缓存的对象可以读、写;
<class-cache usage="transactional"/> (基于事务的策略)
适合放入二级缓存中的数据:
很少被修改
不是很重要的数据, 允许出现偶尔的并发问题
不适合放入二级缓存中的数据:
经常被修改
财务数据, 绝对不允许出现并发问题
与其他应用数据共享的数据
Hibernate常用的两种分页的方式
1. criteria分页
public Page getPage(int currentPage,int pageSize,Criterion...crts){
Criteria c=session.createCriteria(House.class);
List list=null;
for (int i = 0; i < crts.length; i++) {
c.add(crts[i]);
}
c.setProjection(Projections.rowCount());
int totalRecord=Integer.valueOf(c.uniqueResult().toString());
c.setProjection(null);
c.setFirstResult((pageSize)*(currentPage-1));
c.setMaxResults(pageSize);
list=c.list();
Page page=new Page();
page.setCurrentPage(currentPage);
page.setPageSize(pageSize);
page.setTotalRecord(totalRecord);
page.setList(list);
return page;
}
2. hql分页
public Page getPage(int currentPage,int pageSize,String hql,Object...args){
String countHql="select count(*) "+hql.substring(hql.indexOf("from"));
Session session=HibernateUtil.getInstance().getSession();
Query query=session.createQuery(countHql);
for (int i = 0; i < args.length; i++) {
query.setParameter(i, args[i]);
}
int totalRecord=Integer.valueOf(query.uniqueResult()+"");
query=session.createQuery(hql);
for (int i = 0; i < args.length; i++) {
query.setParameter(i, args[i]);
}
query.setFirstResult(pageSize*(currentPage-1));
query.setMaxResults(pageSize);
List<House> list=(List<House>)query.list();
Page page=new Page();
page.setCurrentPage(currentPage);
page.setPageSize(pageSize);
page.setTotalRecord(totalRecord);
page.setList(list);
return page;
}
喜欢就加关注哦
--------------------------------------------------------------------------
老铁福利:
本公众号是分享知识,共同学习、交流的平台,欢迎大家踊跃推荐,共同打造一个共建共享的平台!作为礼物: 回复以下文字可自动获取相关资料:
回复:"高并发"可获取 JAVA高并发秒杀系统实战系列视频
回复“jvm” 可获取深入理解java虚拟机电子书以及全套视频讲解资料
回复“javase” 可获取 java基础相关的整理资料;
回复“html” 可获取html+css+js 相关的整理资料;
回复“shm” 可获取Struts+Hibernate+MyBatis相关的整理资料;
回复“数据库” 可获取数据库相关知识整理资料;
回复"springcloud" 可获取Spring Cloud微服务实战电子书;
回复:"鸟哥" 可获取鸟哥linux 私房菜相关的电子书;
更多的惊喜敬请期待!
微信扫一扫
关注该公众号
标签:evel ber sql数据库 max mil 推荐 show 范围 abstract
原文地址:https://www.cnblogs.com/wangdong811/p/10336245.html