一、对象的状态
1.瞬时/临时状态(Transient Objects)
使用new操作符初始化的对象不是立刻就持久化的,他们的状态是瞬时的。
(1) 不处于Session的缓存中,也可以说,不被任何一个Session实例关联。
(2) 在数据库中没有对应的记录。
2.持久化状态(Persist Objects)
持久实例是任何具有数据库标识的实例。它有持久化管理器Session统一管理,持久实例是在事务中进行操作的———他们的状态在事务结束时同数据库进行同步。
(1) 位于一个Session实例的缓存中,也可以说,持久化对象总是被一个Session实例关联。
(2) 持久化对象和数据库中的相关记录对应。
(3) Session在清理缓存时,会根据持久化对象的属性变化,来同步更新数据库。
3.离线/游离对象(Detached Objects)
Session关闭之后,持久化对象就变为离线对象。离线表示这个对象不能再与数据库保持同步,他们不再受Hibernate管理。
(1) 不再位于Session的缓存中,也可以说,游离对象不被Session关联。
(2) 游离对象是由持久化对象转变过来的,因此在数据库中可能还存在与它对应的记录(前提条件是没有其他程序删除了这条记录)。
4.对象状态转换图
5.核心代码
Session session = SessionUtils.getSession();
Transaction transaction = session.beginTransaction();
User user = (User) session.get(User.class, 1);
user.setName(“jack”);
user.setAge(30);
user.setBirthday(new Date());
transaction.commit();
6.完整案列
JavaBean代码
public class User
{
private int userId;
private String userName;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
@Override
public String toString() {
return "User [userId=" + userId + ", userName=" + userName + "]";
}
}
状态代码
public class App1_status
{
private static SessionFactory sf;
static {
sf = new Configuration()
.configure()
.addClass(User.class) // 测试时候使用
.buildSessionFactory();
}
//1. 对象状态的转换
@Test
public void testSaveSet() throws Exception
{
Session session = sf.openSession();
session.beginTransaction();
//创建对象【临时状态】
//User user = new User();
//user.setUserName("Jack22222");
//保存【持久化状态】
//session.save(user);
// 会反映到数据库
//user.setUserName("Jack333333");
// 查询
User user = (User) session.get(User.class, 5);
// hibernate会自动与数据库匹配(一级缓存),如果一样就更新数据库
user.setUserName("Tomcat");
session.getTransaction().commit();
session.close();
user.setUserName("Jack444444444");
//打印【游离状态】
System.out.println(user.getUserId());
System.out.println(user.getUserName());
}
@Test
public void bak() throws Exception {
Session session = sf.openSession();
session.beginTransaction();
session.getTransaction().commit();
session.close();
}
}
二.一级缓存
1).Hibenate中一级缓存,也叫做session的缓存,它可以在session范围内减少数据库的访问次数! 只在session范围有效! Session关闭,一级缓存失效!
2).当调用session的save/saveOrUpdate/get/load/list/iterator方法的时候,都会把对象放入session的缓存中。
3).Session的缓存由hibernate维护, 用户不能操作缓存内容; 如果想操作缓存内容,必须通过hibernate提供的evit/clear方法操作。
特点:
只在(当前)session范围有效,作用时间短,效果不是特别明显!
在短时间内多次操作数据库,效果比较明显!
1.缓存相关几个方法的作用
session.flush(); 让一级缓存与数据库同步
session.evict(arg0); 清空一级缓存中指定的对象
session.clear(); 清空一级缓存中缓存的所有对象
2.批量操作使用使用
Session.flush(); // 先与数据库同步
Session.clear(); // 再清空一级缓存内容
3.不同的session是否会共享缓存数据?
不会
4.list与iterator查询的区别?
list()
一次把所有的记录都查询出来,
会放入缓存,但不会从缓存中获取数据
Iterator
N+1查询; N表示所有的记录总数
即会先发送一条语句查询所有记录的主键(1),
再根据每一个主键再去数据库查询(N)!
会放入缓存,也会从缓存中取数据!
5.代码实例
javaBean代码
public class User
{
private int userId;
private String userName;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
@Override
public String toString() {
return "User [userId=" + userId + ", userName=" + userName + "]";
}
}
xml文件配置
<hibernate-mapping package="包名">
<class name="User" table="t_user">
<id name="userId" column="id">
<generator class="native"></generator>
</id>
<property name="userName"></property>
</class>
</hibernate-mapping>
测试代码
public class App2_cache
{
private static SessionFactory sf;
static {
sf = new Configuration()
.configure()
.addClass(User.class) // 测试时候使用
.buildSessionFactory();
}
@Test
public void testCache() throws Exception {
Session session = sf.openSession();
session.beginTransaction();
User user = null;
// 查询
user = (User) session.get(User.class, 5);// 先检查缓存中是否有数据,如果有不查询数据库,直接从缓存中获取
user = (User) session.get(User.class, 5);// 先检查缓存中是否有数据,如果有不查询数据库,直接从缓存中获取
session.getTransaction().commit();
session.close();
}
@Test
public void flush() throws Exception {
Session session = sf.openSession();
session.beginTransaction();
User user = null;
user = (User) session.get(User.class, 5);
user.setUserName("Jack");
// 缓存数据与数据库同步
session.flush();
user.setUserName("Jack_new");
session.getTransaction().commit(); // session.flush();
session.close();
}
@Test
public void clear() throws Exception {
Session session = sf.openSession();
session.beginTransaction();
User user = null;
// 查询
user = (User) session.get(User.class, 5);
// 清空缓存内容
// session.clear(); // 清空所有
session.evict(user);// 清除指定
user = (User) session.get(User.class, 5);
session.getTransaction().commit(); // session.flush();
session.close();
}
@Test
public void sessionTest() throws Exception {
Session session1 = sf.openSession();
session1.beginTransaction();
Session session2 = sf.openSession();
session2.beginTransaction();
// user放入session1的缓存区
User user = (User) session1.get(User.class, 1);
// user放入session2的缓存区
session2.update(user);
// 修改对象
user.setUserName("New Name"); // 2条update
session1.getTransaction().commit(); // session1.flush();
session1.close();
session2.getTransaction().commit(); // session2.flush();
session2.close();
}
}
三.懒加载
1. get、load方法的区别
get: 及时加载,只要调用get方法立刻向数据库查询
load:默认使用懒加载,当用到数据的时候才向数据库查询。
2.懒加载
概念:当用到数据的时候才向数据库查询,这就是hibernate的懒加载特性。
目的:提供程序执行效率!
3.lazy 值
true 使用懒加载
false 关闭懒加载
extra (在集合数据懒加载时候提升效率)
在真正使用数据的时候才向数据库发送查询的sql;
如果调用集合的size()/isEmpty()方法,只是统计,不真正查询数据!
4.懒加载异常
Session关闭后,不能使用懒加载数据!如果session关闭后,使用懒加载数据报错:org.hibernate.LazyInitializationException: could not initialize proxy - no Session。
如何解决session关闭后不能使用懒加载数据的问题
方式1:先使用一下数据dept.getDeptName();
方式2:强迫代理对象初始化Hibernate.initialize(dept);
方式3:关闭懒加载设置lazy=false;
方式4:在使用数据之后,再关闭session!
本文介绍了ORM中对象的不同状态及其转换过程,并详细探讨了一级缓存的工作原理及懒加载特性,帮助理解Hibernate等框架如何高效操作数据库。
250

被折叠的 条评论
为什么被折叠?



