缓存、加载、检查、状态

本文深入探讨了Hibernate ORM框架的使用技巧,包括一对多和多对多关系的实现方式,对象的状态管理,以及一、二级缓存的工作原理。通过具体示例说明了如何利用Hibernate简化Java应用与数据库之间的交互。

注解实现的一对多

@Table(name = "persons")

@Entity

public class Person {

@Id

@Column(name = "person_id")

@GenericGenerator(name = "myid", strategy = "uuid")

@GeneratedValue(generator = "myid")

private String id;

@Column(name="person_name")

private String name;

@OneToMany

@Cascade(value=org.hibernate.annotations.CascadeType.SAVE_UPDATE)

@JoinColumn(name="car_personid")

private List<Car> cars = new ArrayList<>();

 

 

@Table(name="cars")

@Entity

public class Car {

@Id

@Column(name="car")

@GenericGenerator(name="uuid",strategy="uuid")

@GeneratedValue(generator="uuid")

private String id;

private String name;

@ManyToOne

@JoinColumn(name="car_personid")

private Person person;

 

 

注解实现的多对多

 

     Stud{

        @ManyToMany

        @JoinTable(name=”sc”,@JsonColumn(name=”sc_sid”,@reversJoinColum(name=”sc_cid”)

        Set<Course> set:

    

     }

 

 

 

 

对象的状态,一级缓存、二级缓存。

 

 

 

1:对象的状态

•瞬时(Transient)  —  由  new 操作符创建,且尚未与Hibernate

Session 关联的对象被认定为瞬时(Transient)的。瞬时(Transient)对象不会被持久化到数

据库中,也不会被赋予持久化标识(identifier)。 如果瞬时(Transient)对象在程序中没

有被引用,它会被垃圾回收器(garbage collector)销毁。 使用 Hibernate  Session 可以将其

变为持久(Persistent)状态。(Hibernate会自动执行必要的SQL语句)

 

Person p = new Person ();  领域对象,这个对象 还没有与Sesssion创建关系此时叫瞬时

 

•持久(Persistent)  —  持久(Persistent)的实例在数据库中有对应的记录,并拥有一

个持久化标识(identifier)。  持久(Persistent)的实例可能是刚被保存的,或刚被加载

的,无论哪一种,按定义,它存在于相关联的 Session 作用范围内。 Hibernate会检测到处于持

久(Persistent)状态的对象的任何改动,在当前操作单元(unit of work)执行完毕时将对

象数据(state)与数据库同步(synchronize)。 开发者不需要手动执行 UPDATE 。将对象从持

久(Persistent)状态变成瞬时(Transient)状态同样也不需要手动执行  DELETE 语句。

 

 

Session.ssave(p);//此时的p对象叫持久,与一个Session相关

 

 

•脱管(Detached) — 与持久(Persistent)对象关联的 Session 被关闭后,对象就变为脱管

(Detached)的。对脱管(Detached)对象的引用依然有效,对象可继续被修改。脱管

(Detached)对象如果重新关联到某个新的  Session 上, 会再次转变为持久(Persistent)的

(在Detached其间的改动将被持久化到数据库)。 这个功能使得一种编程模型,即中间会给用

户思考时间(user think-time)的长时间运行的操作单元(unit of work)的编程模型成为可

能。我们称之为应用程序事务,即从用户观点看是一个操作单元(unit of work)。

 

Session.close();

 

P.setname(“..”) 不会影响数据库中的值。

 

 

2:状态的与脏检查

@Test

public void test() {

Session s = HibernateUitls.openSession();

s.beginTransaction();

//根据id查询这个Person对象

Person p =

s.get(Person.class, "4028806a556d8c5701556d8c598b0000");//此时p对象叫持久化状态

p.setName("Smith");//脏检查

//s.update(p);

s.getTransaction().commit();

s.close();

}

 

3:懒加载

Session.get(Class,id) : 非懒加载,如果id不存在,则返回null- 命中数据库。

Session.load(CLass,id) :懒加载  - r返回的是一个代理,即使是id不存在,也返回一个对象

 

 <class name="cn.hib.domain.Person" table="persons" lazy="false">

        <id name="id" type="java.lang.String" length="32">

 

Session.load(CLass,id)  方法的使用的特点:

    Session s = HibernateUitls.openSession();

s.beginTransaction();

 

Stud stud = s.get(Stud.class, "S002");

//只是为了设置关系,没有必要命中数据库,只要知道C001的id即可

Course c = s.load(Course.class, "C001");

stud.getCourses().add(c);

 

s.getTransaction().commit();

s.close();

 

4:延迟加载

Enumerated Values :

- true  

- false

- extra  延迟加载

<set name="courses" table="sc" cascade="save-update" lazy="extra">

<key column="sc_sid"></key>

<many-to-many class="cn.hib.domain.Course" column="sc_cid"></many-to-many>

</set>

 

5:一级缓存与二级缓存

Session级别的缓存:一级缓存。它的特点是:容量没有限制。
                  事务级别的缓存,生命周期很短。

           openSession() :..开始。

           Session.close(); 关闭

                   一级缓存默认是打开的,且无法关闭。

 

SessionFactory级别的缓存 -

                默认的是关闭的。必须配置以后才可以打开。

                所有Session都共享同一个二级缓存。JVM级别的缓存。

                容量是配置,且必须要使用第三方的框架。

 

1:一级缓存

@Test

public void test() {

Session s = HibernateUitls.openSession();

Person p1 = s.get(Person.class, "S001");//执行过程是:1:先去命中一级缓存,2:再去命中二级缓存 3:于是命中了数据库

                                         //4:将这个对象放到二级缓存中去  5:放到一级缓存中去

Person p2 = s.get(Person.class, "S001");

System.err.println(p1==p2);

 

s.close();

 

 

 

可以操作删除一级缓存中的数据:

Session s = HibernateUitls.openSession();

Person p1 = s.get(Person.class, "S001");//执行过程是:1:先去命中一级缓存,2:再去命中二级缓存 3:于是命中了数据库

                                         //4:将这个对象放到二级缓存中去  5:放到一级缓存中去

 

//s.evict(p1);//删除放到一级缓存中的p1这一个对象

s.clear();//删除放到一级缓存中的所有对象

Person p2 = s.get(Person.class, "S001");

System.err.println(p1==p2);

 

s.close();

 

2:一级缓存与批量处理

 

 

@Test

public void test() {

Session s = HibernateUitls.openSession();

s.beginTransaction();

 

for(int i=0;i<50;i++){

Person p = new Person();

p.setName("Jerry"+i);

s.save(p);

if(i%20==0){

s.flush();

s.clear();

}

}

 

 

 

6:二级缓存

 

SessionFactory级别的缓存。

 

步1:添加第三方的缓存包 ehcache

 

 

<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-ehcache -->

<dependency>

    <groupId>org.hibernate</groupId>

    <artifactId>hibernate-ehcache</artifactId>

    <version>5.1.0.Final</version>

</dependency>

 

 

步2:添加ehcache的配置文件

    <defaultCache

        maxElementsInMemory="100"

        eternal="false"

        timeToIdleSeconds="120"

        timeToLiveSeconds="120"

        overflowToDisk="true"

        />

</ehcache>

 

步3:配置对哪一个类进行二级缓存

 

<!-- 配置启用二级缓存 -->

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

<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

 

 

<mapping resource="cn/hib/domain/Person.hbm.xml" />

<mapping resource="cn/hib/domain/Stud.hbm.xml" />

 

<!-- 配置哪一个类进行二级缓存 -->

<class-cache usage="read-only" class="cn.hib.domain.Person" />

 

 

<!-- 配置哪一个类进行二级缓存 -->

<class-cache usage="read-only" class="cn.hib.domain.Person"/>

 

测试:

   打开两个Session

@Test

public void test() {

Session s = HibernateUitls.openSession();

Person p = s.get(Person.class, "S001");

s.close();

 

 

Session s2 = HibernateUitls.openSession();

Person p2 = s2.get(Person.class, "S001");

s2.close();

 

 

 

 

7:统计二级缓存的命中次数

<!-- 打开统计信息 -->

<property name="generate_statistics">true</property>

 

public class Demo01 {

@Test

public void test() {

Session s = HibernateUitls.openSession();

Person p = s.get(Person.class, "S001");//hit=0 miss=1 put=1

s.clear();

Person pp = s.get(Person.class, "S001");//hit=1,miss=1,put=1

s.close();

 

//删除二级缓存中的数据

HibernateUitls.getSessionFactory().getCache().evictAllRegions();

 

Session s2 = HibernateUitls.openSession();

Person p2 = s2.get(Person.class, "S001");//hit=1,miss=2,put=2

s2.close();

 

SessionFactory sf =

HibernateUitls.getSessionFactory();

Statistics stat =  sf.getStatistics();

System.err.println("命中数次:"+stat.getSecondLevelCacheHitCount());

System.err.println("没有命中:"+stat.getSecondLevelCacheMissCount());

System.err.println("放过几次:"+stat.getSecondLevelCachePutCount());

}

}

 

转载于:https://my.oschina.net/dtz/blog/701361

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值