对象的三种状态
临时状态
例如:你在大街上遇到一个陌生人你们在进行交流相当于临时状态
持久状态
例如:小学同学玩到现在还一直玩到一起叫做持久状态
游离状态
例如:之前关系比较好现在几年没联系了(如果见到可能关系和以前一样或许会陌生)叫做游离状态
三种状态
当你去new实体类的时候加载到session中它们是处于临时状态的,当session加载javabean去调用save的时候它会变成持久的状态,如果把session关闭的话或者提交事务的话那么当前的对象就处于游离状态,当游离状态想回到持久状态的话它又可以去进行更新的操作回到持久状态(其实关闭之后它还是会存在缓存中一段时间处于游离状态),当update后它可能会变到临时状态也有可能会回到游离状态,hibernate管理对象的三种状态实际上是hibernate对对象的操作在哪一个地方。
Hibernate 中 load()和 get()区别
把hibernate必不可少的几个步骤封装成一个工具类,把通用的部分构成共用的部分。
package com.liyingdong.util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class SessionFactoryUtils {
private static final String HIBERNATE_CONFIG_FILE = "hibernate.cfg.xml";
private static ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
// 创建数据库的会话工厂
private static SessionFactory sessionFactory;
// 读取hibernate核心配置
private static Configuration configuration;
static {
try {
configuration = new Configuration();
configuration.configure(HIBERNATE_CONFIG_FILE);
// 创建Session会话工厂
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
e.printStackTrace();
}
}
public static Session openSession() {
Session session = threadLocal.get();
if (null == session) {
session = sessionFactory.openSession();
threadLocal.set(session);
}
return session;
}
public static void closeSession() {
Session session = threadLocal.get();
if (null != session) {
if (session.isOpen())
session.close();
threadLocal.set(null);
}
}
public static void main(String[] args) {
Session session = SessionFactoryUtils.openSession();
System.out.println("Session状态:" + session.isOpen());
System.out.println("Session会话已打开");
SessionFactoryUtils.closeSession();
System.out.println("Session会话已关闭");
}
}
立即加载 get()
举例:实质上就是你需要我就立马给你,比如当发生地震的时候立即跑出去。
特点:get 方法检索不到结果的话,返回结果为 null
;
检索机制中:get
`不支持延迟加载,
package com.liyingdong.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.liyingdong.entity.User;
import com.liyingdong.util.SessionFactoryUtils;
public class Demo2 {
public void users() {
Session session = SessionFactoryUtils.openSession();
//开启事务
Transaction ts= session.beginTransaction();
User user=new User();
user.setId(6666);
User user2 = session.get(User.class, user.getId());
//提交事务
ts.commit();
//释放资源
session.close();
System.out.println(user2);
}
public static void main(String[] args) {
Demo2 d=new Demo2();
d.users();
}
}
结果:
延迟加载 load()
举例:当下课的时候你在打游戏别人叫你去有事,你说等我打完这一把。
检索机制中:load 支持延迟加载(懒加载)
第一种情况
特点:load()方法检索不到结果的话,则会出现 ObjectNotFoundException 异常
代码:
package com.liyingdong.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.liyingdong.entity.User;
import com.liyingdong.util.SessionFactoryUtils;
public class Demo2 {
public void users() {
Session session = SessionFactoryUtils.openSession();
//开启事务
Transaction ts= session.beginTransaction();
User user=new User();
user.setId(666);
User user2 = session.load(User.class, user.getId());
System.out.println(user2);
//提交事务
ts.commit();
//释放资源
session.close();
}
public static void main(String[] args) {
Demo2 d=new Demo2();
d.users();
}
}
第二种情况
为什么会报错呢?
它说无法初始化代理-没有会话,其实很简单你可以这样去理解,load它是延迟加载只有你去用的时候急得不得了的时候它才会去加载,其实问题就是我在输出之前关闭了session,才导致它加载报错
。
举例:一个公司给你布置了一个任务,等你去做的时候发现公司倒闭了,这个时候就根本做不了了,同理代码中你要用到user2的时候它才会去加载并且给你输出,但是你关闭了session所以就加载不了了
。
如果把System.out.println(user2);放到User user2 = session.load(User.class, user.getId());下面它是不会报错的。
代码:
package com.liyingdong.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.liyingdong.entity.User;
import com.liyingdong.util.SessionFactoryUtils;
public class Demo2 {
public void users() {
Session session = SessionFactoryUtils.openSession();
//开启事务
Transaction ts= session.beginTransaction();
User user=new User();
user.setId(3);
User user2 = session.load(User.class, user.getId());
//提交事务
ts.commit();
//释放资源
session.close();
System.out.println(user2);
}
public static void main(String[] args) {
Demo2 d=new Demo2();
d.users();
}
}
代理对象
我们去取id的时候是取的session中的缓存对象User中的,而且不是session执行的命令的结果集中的,被缓存的user就是所谓的代理
。
代码:
package com.liyingdong.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.liyingdong.entity.User;
import com.liyingdong.util.SessionFactoryUtils;
public class Demo2 {
public void users() {
Session session = SessionFactoryUtils.openSession();
//开启事务
Transaction ts= session.beginTransaction();
User user=new User();
user.setId(3);
User user2 = session.load(User.class, user.getId());
System.out.println(user2.getId());
//提交事务
ts.commit();
//释放资源
session.close();
}
public static void main(String[] args) {
Demo2 d=new Demo2();
d.users();
}
}
并发控制
查询是不会造成并发状况的,我们来看一下update它是会进行并发计算的,hibernate中提供了并发控制举例下面,A角色和B角色同一时间去修改首先是查询出来,数据库有一个默认隐藏字段version,假设两个人拿到的都是1,比如两个人相隔零点几秒去update,第一个人修改后数据库进行了更新version也更新了,那么第二个人where 条件比对的时候vresion还是1,不会报错它会让第二个人重新提交请求。
version=2 2
A:
update t_student set sname=‘zs’, version=version+1
where sid = 8 and version=1
B:
update t_student set sname=‘ls’, version=version+1
where sid = 8 and version=2
快照
User user=session.get(User.class,user.getId());
我们看一下通过user中的id查询结果放到User中然后在存入session,此时处于持久状态,其实相当于副本,当我们查询结果放到session中的时候,别人又修改数据库了此时我们拿到的是更新前的数据相当于给自己拍了一张照片,影响不到自己(源头)。
一级缓存
当 hibernate 根据 ID 访问数据对象时,首先会从 session 一级缓存中查;查不到,就查询数据库把数据放入session中相当于实现了一次快照。
一级缓存:又称为session级别缓存存在于 session 的生命周期中,当 session 关闭时,session 所管理的一级 缓存也会被立即清除,这是由hibernate自己管理的。
hibernate中知道那些数据被更新和没被更新当你访问的数据在数据库中没被更新的时候是直接访问缓存中的数据,相当于少了一次访问数据库的过程让效率更高了,当你访问的数据被更新了它会去查询数据库中的数据到快照中。