hibernate查漏补缺2

Hibernate对象状态

瞬时(transient):由new操作符创建,且尚未Hibernate Session关联。瞬时对象不会被持久化到数据库,也不会被赋予持久化标识。

持久(persistent):持久化的实例在数据库中有对应的记录,并拥有一个持久化标识。

持久化的实例可能是刚被保存,或刚被加载的,无论哪一种,它都只存在于相关联的Session作用范围内。这点很重要。Hibernate会检测处于持久化状态的对象的任何变动,在当前操作单元执行完毕时,将对对象数据与数据库同步。

脱管(detached):在与持久化对象关联的Session关闭后,对象就变成脱管状态。

Hibernate的第一级缓存(Session缓存)

当调用Session的save(),update(),saveOrUpdate(),load()或get()方法,以及调用Query接口的list(),iterator()或filter()方法时,如果缓存中没有相应的对象,Hibernate便会将对象添加到Session缓存中。

比如:

        Transaction transaction = session.beginTransaction();
        Feeling feeling = (Feeling) session.get(Feeling.class, 1);
        System.out.println(feeling);
        System.out.println(feeling.getFeelingComments());
        Feeling feeling1 = (Feeling) session.get(Feeling.class, 1);
        transaction.commit();
Hibernate:
    select
        feeling0_.feeling_id  as feeling1_1_0_,
        feeling0_.content as content1_0_,
        feeling0_.id as id1_0_
    from
        feeling feeling0_
    where
        feeling0_.feeling_id =?
[email protected]
Hibernate:
    select
        feelingcom0_.feeling_id as feeling3_1_1_,
        feelingcom0_.feelingComment_id  as feelingC1_1_,
        feelingcom0_.feelingComment_id  as feelingC1_2_0_,
        feelingcom0_.content as content2_0_,
        feelingcom0_.feeling_id as feeling3_2_0_,
        feelingcom0_.id as id2_0_
    from
        feeling_comment feelingcom0_
    where
        feelingcom0_.feeling_id=?
[[email protected], [email protected], [email protected], [email protected]]

可以看到第二次的get()并没有生成sql.

可以使用1.evict()从缓存中清除指定的持久化对象。2.clear()清除所有。。。。多数情况下,不提倡通过上面两个方法管理缓存。

当Session缓存中对象的属性发生变化时,Session并不会立即清理缓存并执行相关的sql,使数据库同步,而只是在特点的时间点才清理缓存。这使得Session可以把几条相关的sql合并成一条,提升性能。

上面的特点的时间点包括:

1.调用Transaction的commit()方法。这时清理缓存,然后向数据库提交事务。这样做是为了最大限度减少数据库的访问和尽可能的缩短当前事务对数据库中相关资源的锁定时间。

2.执行一些查询操作。这样做是为了保证查询返回的结果是即时,正确的。

3.显式调用flush().注意,flush()不会提交事务,数据还有可能rollback.

对于flush()最常用的用法当然是批量操作了。比如批量插入100000条数据。

for(int i=1;i<100000;i++){
    Customer c=new Customer();
    session.save(c);
    if(i%20==0){
         session.flush();
         session.clear();
    }
}

设置hibernate.jdbc.batch_size=20。一定数量(20)时强制刷出,使缓存与数据库同步(数据写入数据库),然后清空所有缓存,避免内存溢出。

load()和get()

http://www.cnblogs.com/binjoo/articles/1621254.html

注意两者的运行流程:get方法首先查询session缓存,没有的话查询二级缓存,最后查询数据库;反而load方法创建时首先查询session缓存,没有就创建代理,实际使用数据时才查询二级缓存和数据库。

对load(),如果只是Feeling feeling = (Feeling) session.load(Feeling.class, 1);是不会发出sql的,只有像System.out.println(feeling);这样使用了feeling才会发出。

load()只是生成类的动态代理,并没有将数据库的数据加载到相应的类中,所以适合在数据更新或为表插入外键数据时使用,

hibernate查漏补缺1中的那个好友分类例子中,插入新加的好友并把他加入到已经存在的分类中。

        Friend_Category fc = new Friend_Category();
        fc.setCategory_name("已经存在的好友分类");
        User_Friend_pk pk = new User_Friend_pk();
        pk.setFriend_name(“新好友”);
        pk.setName("TheViper");
        User_Friend uf = new User_Friend();
        uf.setUser_friend_pk(pk);
        Friend_Category fc1 = (Friend_Category) session.load(
                Friend_Category.class, 1);
        uf.setFriend_categorys(fc1);

        // uf.setSort("好基友");
        session.saveOrUpdate(fc1);
        session.save(uf);

注意,这时对load的Friend_Category要用saveOrUpdate(),否则会出现异常 org.hibernate.PersistentObjectException: uninitialized proxy passed to save()。

很多人都在用Spring的HibernateTemplate模板。它有个不好的地方,比如:

        Feeling f = hibernateTemplate.load(Feeling.class, 1);
        System.out.println(f);

返回异常 org.hibernate.LazyInitializationException: could not initialize proxy - no Session

原因在于HibernateTemplate和Spring的其他dao模板如JdbcTemplate一样,走的是下面的流程:

1.准备资源->2.启动->3.数据访问->4.返回数据->5.提交/回滚事务->6.处理异常关闭资源

其中的3,4是我们写的,其他的都是模板帮我们做的。也就是说,每次用了HibernateTemplate的方法后,HibernateTemplate都会自己关闭资源,防止数据库连接,内存泄漏,而关闭的资源中就包括了Hibernate的Session.Session,自然就找不到Session缓存和类的动态代理(load()返回的)了。

Cascade

在<set>,<one-to-one>,<many-to-one>(个人觉得在many-to-one里面很没用)中使用。

Hibernate日志

Hibernate第二级缓存

进程或集群范围内的缓存,SessionFactory级别,而第一级缓存是事务范围的缓存。第二级缓存中存放的是对象的散装数据。

第二级缓存的4种并发访问策略,每一种策略对应一种事务隔离级别。

  • 事务型(transactional):仅在受管理的环境中适应。提供repeatable read事务隔离级别,适用于经常访问但很少被修改的数据,可防止脏读和不可重复读这类并发问题。
  • 读写型(read-write):read committed事务隔离级别,仅在非集群的环境中适用。适用于经常访问但很少被修改的数据,防止脏读。
  • 非严格读写型(nonstrict-read-write):不保证缓存与数据库中数据的一致性。如果两个事务访问缓存中的相同数据,则必须为该数据一个很短的数据过期时间,以避免脏读。适用于极少被修改且允许偶尔脏读的数据这种情况。
  • 只读型(read-only):适用于从来不会修改的数据。

transactional隔离级别最高,并发性能最低;read-only则反之。

缓存插件可分为进程范围内缓存(EHCache,OSCache),集群范围内缓存(SwarmCache,JbossCache).其中SwarmCache不支持查询缓存。

配置hibernate.cfg.xml

        <property name="hibernate.cache.use_second_level_cache">true</property>
        <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

Hibernate允许在类和集合上配置二级缓存,在<class>和<set>上都有<cache>子元素.

用法:<cache usage="transactional|read-write|nonstrict-read-write|read-only" region="regionName" include="all|non-lazy"/>

usage:指定并发访问策略。region:指定二级缓存的区域名字,默认为类或集合的名字。include:指定当缓存一个对象时,会不会缓存它的映射为延迟加载的属性。默认all.

ehcache配置

配置<cache>的时候有一点要注意,在<set>下配置了<cache>的话还需要在<set>的另一边的<class>下也配置<cache>才会有效。

管理二级缓存

sessionFactory.evict(Category.class,new Long(1));//清除二级缓存中id为1的Category对象

sessionFactory.evict(”mypack.Category“);//清除二级缓存中Category类的所有对象

sessionFactory.evictCollection(”mypack.Category.items“);//清除二级缓存中Category类的所有对象的items集合

Session与二级缓存的交互模式:

用org.hibernate.CacheMode的5个静态常量表示。

  • CacheMode.NORMAL:正常模式(默认),Session会向二级缓存中读取和写入数据。
  • CacheMode.IGNORE:忽略模式,Session不会向二级缓存读取,也不会写入数据。
  • CacheMode.GET:Session对二级缓存只读不写。
  • CacheMode.PUT:Session对二级缓存只写不对。
  • CacheMode.REFRESH:刷新模式,Session不会从二级缓存中读取数据,但会向其中写入从数据库读取的数据。和PUT的区别在于REFRESH会忽略配置文件中的hibernate.cache.use_minimal_puts属性,强制刷新二级缓存中的所有数据。

用法:session.setCacheMode(CacheMode.IGNORE);

时间: 2024-10-16 20:21:59

hibernate查漏补缺2的相关文章

hibernate查漏补缺1

转载请注明: TheViper http://www.cnblogs.com/TheViper SessionFactory接口 一个SessionFactory接口对应一个数据存储源.特点: 1.线程安全.即它的同一个实例可以被应用的多个线程共享. 2.重量级.创建和销毁它的实例所花费的代价很大,所以应用的一个数据库对应一个SessionFactory实例,在初始化时创建. Session接口 持久化管理器,复杂和持久化的相关操作.特点: 1.不是线程安全.2.实例是轻量级的. Hiberna

近来的java小总结(2.1):类的知识的查漏补缺

首先,我是一名新手,所以,要带着批判的眼光来看下面的文章   这篇文章说了些什么? 这文章是我近来8.6号来在编程思想上打的代码,从0~200页的源码接近到在这里,下文正是总结这0~200页的的知识,涉及到接口,内部类.初始化,数值计算的一些细节.此文章不会一下子写完,可能隔一天可能再补下来.因为代码确实有点多.. 注意 1 我的注释不一定正确(不过各小标题和代码一定是正确的,因为是书本上的原话,但是注释不一定正确),如果你确信我的内容的话,你可能会损失很大,因为我只是个菜鸟,我只是来补救一些知

查漏补缺——java多态

---恢复内容开始--- 刚学完java,开始了查漏补缺阶段阶段,为了巩固自己的知识和为别人提供一些微末的帮助决定开通博客,求各位大牛们指出我的不足,不要吝惜言语,也希望我的总结可以对别人有帮助,对自己对他人负责. 开始正文:术语多态:可以定义为“有多种形态”,多态引用是一个一个在不同时刻可以指向不同类型对象的引用变量.通过多态引用可以调用不同的具体的方法. 类方法的多态性的实现有两种方式: 1:方法重载:可以声明多个同名但是参数不同(个数.类型和顺序)的方法.注意呵呵重载方法只能声明在一个类里

近来的java小总结(2.2):类的知识的查漏补缺

1 首先,我是一名新手,所以,要带着批判的眼光来看下面的文章   这篇文章说了些什么? 这文章是我近来8.6号来在编程思想上打的代码,从0~200页的源码接近到在这里,下文正是总结这0~200页的的知识,涉及到接口,内部类.初始化,数值计算的一些细节.此文章不会一下子写完,可能隔一天可能再补下来.因为代码确实有点多.. 注意 1 我的注释不一定正确(不过各小标题和代码一定是正确的,因为是书本上的原话,但是注释不一定正确),如果你确信我的内容的话,你可能会损失很大,因为我只是个菜鸟,我只是来补救一

java知识查漏补缺

一.重写(override)和重载(overload)的区别 二者除了名字相似,其实没什么联系 范围不同:重写发生在同一个类的不同方法之间.重载发生在父类和子类自荐. 前提: 重写要求:方法名相同,参数列表不同,对于返回值类型不要求相同. 重载要求:方法名形同,参数列表也相同.重载是实现多态的关键,注意如果父类中的方法是private类型,那么子类中对应方法不算重载,而相当于是定义了一个新方法. 二.final的用法 修饰类:该类不能被继承 修饰方法:该方法不能被重写 修饰属性:该属性初始化后不

自家用的java小总结(2.4):类的知识的查漏补缺(内部类)

1 2      首先,这是一篇自己用的文章,不对读者承担任何责任,所以,要带着批判的眼光来看下面的文章   1 发现了,得加上输出结果,怕自己出错,~~   这篇文章说了些什么? 这文章是我近来8.6号来在编程思想上打的代码,从0~200页的源码接近到在这里,下文正是总结这0~200页的的知识,涉及到接口,内部类.初始化,数值计算的一些细节.此文章不会一下子写完,可能隔一天可能再补下来.因为代码确实有点多.. 注意 1 我的注释不一定正确(不过各小标题和代码一定是正确的,因为是书本上的原话,但

查漏补缺

查漏补缺[1].this语句:this语句用于构造函数之间进行相互调用.this语句只能定义在构造函数的第一行,因为初始化要先执行.[2].对象的初始化过程 Person p =new Person("hei",10); 1.因为new用到了Person.class,所以先找到Person.class文件加载到内存中 2.执行类中的静态代码块,如果有的话,给Person.class类进行初始化 3.在堆内存中开辟空间,分配内存地址 4.在堆内存中建立对象的特有属性,并进行默认初始化 5

《CSS权威指南》基础复习+查漏补缺

前几天被朋友问到几个CSS问题,讲道理么,接触CSS是从大一开始的,也算有3年半了,总是觉得自己对css算是熟悉的了.然而还是被几个问题弄的"一脸懵逼"... 然后又是刚入职新公司,事情不算多,于是拿起<CSS权威指南>进行"基础学习"+"查漏补缺",本篇文章主要是总结了些自己认为CSS中值的注意的几个知识点(本文知识点仅限本书范围内,若要讲CSS全部样式,那本兽还是选择慢慢懵逼去~). 选择器 这里要说明的是类选择器的嵌套选择与多类

今天开始慢下脚步,开始ios技术知识的查漏补缺。

从2014.6.30 开始工作算起.现在已经是第416天了.不止不觉,时间过的真快. 通过对之前工作的总结,发现,你的知识面,会决定你面对问题时的态度.过程和结果. 简单来讲,知识面拓展了,你才能有更多的备选方法,才更有可能选择到一条最最有效的路. 趁现在正好有时间,时机又正好,开始我的技术总结补缺之路吧. 参考教材<疯狂iOS讲义>.主要原因是,知识比较全面,涉及面比较广.适合查漏补缺. 开始吧.看我能坚持多久. 版权声明:本文为博主原创文章,未经博主允许不得转载.