先理解了hibernate的一级缓存和它的三种状态,才能对后面我要讲解的一对多,一对一、多对多这种映射关系更好的理解.
目录:
1.hibernate的缓存和快照(有些说法没有快照概念)
2.常用的方法理解
3.hibernate的三或四种状态
1. session是有一个缓存,又叫hibernate的一级缓存. session缓存是有一系列java集合构成的,当一个对象被加入到session缓存中,对象的引用就加入到java的集合中, 以后即使应用程序的引用变量中不在引用改对象,只要session缓存不被清空,这个对象一直处于生命周期中.
hibernate需要和数据库打交道,是通过session获得缓存中的关联对象,然后拼接成相应的sql再执行.
具体过程:
1)、首先session将一个对象加入自己的管理范围内,其实也就是把该对象放入自己的一级缓存中。如,session.get(xxx);这个语句就是将xxx保存在自己的一级缓存中,等待事务提交后,hibernate才真正的发sql语句,操作数据库。
2)、在一级缓存中会做些什么事情呢?为什么能够知道是发insert、还是update又或者delete呢?讲讲内部是什么原理。那这里就要提到一个快照的概念了,讲讲内部是什么原理。
package com.cc8w; import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.cc8w.entity.UserEntity; /** * 主要是hibernate缓存的配置 * @author Administrator * session是有一个缓存,又叫hibernate的一级缓存 * session缓存是有一系列java集合构成的,当一个对象被加入到session缓存中,对象的引用就加入到java的集合中, * 以后即使应用程序的引用变量中不在引用改对象,只要session缓存不被清空,这个对象一直处于声明周期中. */ public class AppTest { private Configuration configuration=null; private SessionFactory sessionFactory=null; private Session session=null; private Transaction transaction=null; @Before public void beforeTest() { System.out.println("beforeTest"); //1. 加载Hibernate的核心配置文件 configuration = new Configuration().configure(); //如果在Hibernate的核心配置文件没有设置加载哪个映射文件,则可手动加载映射文件 //configuration.addResource("com/cc8w/mapper/UserMapper.hbm.xml"); //2. 创建SessionFactory对象,类似于JDBC中的连接池 sessionFactory = configuration.buildSessionFactory(); //3. 通过SessionFactory获取到Session对象,类似于JDBC中的Connection session = sessionFactory.openSession(); //4. 手动开启事务,(最好是手动开启事务) transaction = session.beginTransaction(); //5.执行语句写在测试方法里面 } @After public void afterTest() { System.out.println("afterTest"); //6. 事务提交 transaction.commit(); //7. 释放资源 session.close(); sessionFactory.close(); } @Test public void TestCache() { UserEntity user = new UserEntity(); user.setCname("123"); user.setUserName("李123"); user.setCreateTime(new Date()); session.save(user);//加入了一级缓存中,提交事务时insert操作 user.setCname("789"); user.setUserName("李789");//将快照区域的属性值修改,和一级缓存对比,不一样将发起update /** * 在session将user加入一级缓存时,一级缓存和快照区域是一样的,当user改变自己的username属性时,此时将快照区中的user的username属性改变了, * 在事务提交时,会发送insert插入语句,因为使用了session的save语句,将一级缓存中的数据增加到数据库,然后再通过快照区和一级缓存做对比, * 如果不一样的地方,那么就会在发送一个update语句更新,(注意,除了id属性外,其他属性改变会发送update语句,id属性改变,就会报异常.) */ } }
如果没有快照概念这样理解:
如果一个对象以及是持久化状态了,那么此时对该对象进行各种修改,或者调用多次update、save方法时,hibernate都不会发送sql语句,只有当事物提交的时候,此时hibernate才会拿当前这个对象与之前保存在session中的持久化对象进行比较,如果不相同就发送一条update的sql语句,否则就不会发送update语句。
发送的sql语句:
Hibernate: insert into t_admins (username, password, cname, email, create_time, last_time) values (?, ?, ?, ?, ?, ?) Hibernate: update t_admins set username=?, password=?, cname=?, email=?, create_time=?, last_time=? where id=?
session.get()
@Test public void getUser() { //发起select查询,并存到session一级缓存,给快照去复制一份 UserEntity user = session.get(UserEntity.class,6); //修改了快照区,会发出update语句。 user.setCname("李1112"); }
分析图
sql:
Hibernate: select userentity0_.id as id1_0_0_, userentity0_.username as username2_0_0_, userentity0_.password as password3_0_0_, userentity0_.cname as cname4_0_0_, userentity0_.email as email5_0_0_, userentity0_.create_time as create_t6_0_0_, userentity0_.last_time as last_tim7_0_0_ from t_admins userentity0_ where userentity0_.id=? afterTest Hibernate: update t_admins set username=?, password=?, cname=?, email=?, create_time=?, last_time=? where id=?
2. 通过几个方法来深刻理解下缓存:
1) session.evict() :会把指定的缓冲对象进行清除;
2) session.flush()的作用就是将session的缓存中的数据与数据库同步。(也就是不用事务提交缓存就刷出来了,就会发sql语句,事务提交也是一个刷出缓存的方法,)
3) session.clear()的作用就是清除session中的缓存数据(不管缓存与数据库的同步)。
4)session.refresh():会强制发送select语句,以使session缓存中对象的状态和数据表中对应的记录保持一致。该方法的有效性需要配置事务的隔离级别为read commited(读已提交)。
session.evict()
@Test public void testEvict() { //发起select查询,并存到session一级缓存,给快照去复制一份 UserEntity user = session.get(UserEntity.class,6); //将user从session一级缓存中移除(快照区域没删) session.evict(user); //这里不会发送update语句(快照区域和缓存对比,发现无此实例,就什么也不做) user.setCname("李1118"); }
3. Hibernate 的三种实体状态 (下一篇 )
Hibernate有三种实体状态,有瞬时态(transiant),持久态(persistent),游离态(detached)。 简单理解就是,瞬时态指的是刚New 新建的一个对象,没有放在Session时,也没有存储在数据库中。 持久态,指这个对象存储在数据库中,并且存在于Session会话中。 而游离态指的是,这个对象存储在数据库中,但已经不存在于Session会话中。下面是比较官方的说法:
转 参考: https://www.cnblogs.com/whgk/p/6103038.html
https://www.cnblogs.com/yjhrem/articles/2374818.html
三种状态的解析: https://blog.csdn.net/yjltx1234csdn/article/details/83214978