你很了解hibernate吗?

   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 私房菜相关的电子书;
更多的惊喜敬请期待!

微信扫一扫
关注该公众号

猜你喜欢

转载自www.cnblogs.com/wangdong811/p/10336245.html
今日推荐