一、Session中方法
1、开启一个事务:
Transaction beginTransaction()
2、获取一个事务:
Transaction getTransaction()
3、保存一个对象:
Serializable save(Object o)
4、修改一个对象:
void update(Object o)
5、删除一个对象:
void delete(Object o)
6、根据主键查询指定类型的对象:
Object get(Class type,Serializable id)
7、根据hql创建一个查询对象
Query createQuery(String hql)
8、关闭Session:
void close()
9、清除一级缓存所有对象:
void clear()
10、清除一级缓存中制定的对象:
void evict(Object o)
1、事务相关的方法
- Transactionsession.beginTransaction():标记打开当前session绑定的事务对象
- Transactionsession.getTransaction():得到和当前session绑定的事务对象。
2、一级缓存相关
- session.clear():清除一级缓存中所有的对象。
- boolean contains(Objectentity):判断一级缓存中是否有给定的对象。
- session.evict(Objectentity):从一级缓存中清除指定的对象。
- session.flush():把一级缓存中的脏数据同步到数据库中。
- session.refresh(Objectentity):强制重新查询对象,相当于把数据库中的数据同步到一级缓存中。
3、持久化操作相关:
- 1、 session.delete(Object entity):从数据库中删除一个对象
- 2、 session.update(Objectentity):更新一个对象
- 3、session.get(ClassentityType,Serializableid):根据主键查询一个对象
- 4、session.load(ClassentityType,Serializableid):根据主键加载一个对象
- 4.1、load方法是一个延时加载的方法,把对象的获取(SQL)延迟到了真正使用这个对象的时候才发送。
- 4.2、真正使用?当使用一个非主键属性的时候
- 4.3、load实现原理?使用动态代理,为load的domain动态创建了一个子类,在这个子类中,复写所有非主键调用方法,在这些方法中,去发送
- 5、session.save(Objectentity):保存一个对象
- 6、session.persist(Objectentity):保存一个对象
- 6.1、同步JPA的接口方法
- 6.2、和save的区别:在没有事务环境下,save方法会发送INSERT SQL,而persist不会
- 6.3、session.saveOrUpdate():如果对象没有保存到数据库,则保存,如果已经保存过,则更新。在没有事务环境下,saveOrUpdate方法会发送INSERT SQL,merge不会
- 6.4、session.merge():等同于saveOrUpdate()
- 7、session.close():关闭session之后,就不能在使用这个session完成持久化相关的操作
- 8、session.doWork(Work work):Hibernate提供给程序员直接使用JDBC的一个途径
- 9、session.doReturningWork(ReturningWork):Hibernate提供给程序员直接使用JDBC的一种途径
- 10、Serializablesession.getIdentifier(Objectentity):得到一个对象的主键值
4、持久化方法
在Hibernate中persist和方法save方法都表示保存一个对象
- save方法是:Hibernate自身提供的方法
- persist方法是:JPA规范中的方法,Hibernate实现了JPA规范,那么就得提供persist方法
但是persist方法必须运行在事务空间内 - session.save():没有事务环境,也会发送INSERT INTO语句,但是不会保存成功
public void save(User user) {
Session session = HibernateUtil.getHibernateSession();
//5、设置事务的开启状态
// session.beginTransaction();
//6、具体操作
session.save(user);
//7、提交事务
// session.getTransaction().commit();
}
Hibernate:
insert
into
t_user
(name, date)
values
(?, ?)
- session.persist():没有事务环境,不会发送INSERT INTO语句(推荐),不会保存成功
public void save(User user) {
Session session = HibernateUtil.getHibernateSession();
//5、设置事务的开启状态
// session.beginTransaction();
//6、具体操作
// session.save(user);
session.persist(user);
//7、提交事务
// session.getTransaction().commit();
}
5、保存或更新方法:
session.saveOrUpdate(Object en):如果对象之前没有存储到数据库,则保存,如果已经保存过,则更新。
如果对象存在OID,则update
如果对象不存在OID,则save
merge方法是JPA提供的方法,功能和saveOrUpdate等价
merge方法相当于saveOrUpdate方法,必须运行在事务空间内
5.1、saveOrUpdate没有事务
public void saveOrUpdate(User user) {
Session session = HibernateUtil.getHibernateSession();
session.saveOrUpdate(user);
}
Hibernate:
insert
into
t_user
(name, date)
values
(?, ?)
- 5.2、saveOrUpdate有事务
public void saveOrUpdate(User user) {
Session session = HibernateUtil.getHibernateSession();
session.beginTransaction();
session.saveOrUpdate(user);
session.getTransaction().commit();
}
- 5.2.1、user对象没有OID
Hibernate:
insert
into
t_user
(name, date)
values
(?, ?)
- 5.2.2、user对象有OID
Hibernate:
update
t_user
set
name=?,
date=?
where
id=?
-
小结:
saveOrUpdate-
1、没有事务时:(操作不成功)
- 1.1:没有OID时,发送INSERT INTO语句
- 1.2:存在OID时,没有发送UPDATE语句
-
2、存在事务环境:(操作成功)
- 2.1:没有OID时,发送INSERT INTO语句
- 2.2:存在OID时,发送UPDATE语句
-
5.3、merge没有事务
没有OID:没有发送INSERT INTO语句
public void saveOrUpdate(User user) {
Session session = HibernateUtil.getHibernateSession();
session.merge(user);
}
存在OID:发送SELECT语句,没有发送UPDATE语句
Hibernate:
select
user0_.id as id1_0_0_,
user0_.name as name2_0_0_,
user0_.date as date3_0_0_
from
t_user user0_
where
user0_.id=?
- 5.4、merge存在事务环境
没有OID:发送INSERT INTO语句
public void saveOrUpdate(User user) {
Session session = HibernateUtil.getHibernateSession();
session.beginTransaction();
session.merge(user);
session.getTransaction().commit();
}
Hibernate:
insert
into
t_user
(name, date)
values
(?, ?)
存在OID:发送SELECT语句,发送UPDATE语句
Hibernate:
select
user0_.id as id1_0_0_,
user0_.name as name2_0_0_,
user0_.date as date3_0_0_
from
t_user user0_
where
user0_.id=?
Hibernate:
update
t_user
set
name=?,
date=?
where
id=?
6、get和load方法
get方法返回的总是持久化状态的对象;get方法立刻发送一条SELECT语句,结果可以用if-null来判断对象是否为空
load方法并不会立刻发送一条SELECT语句去查询对象,而要到了真正在使用一个非主键属性的时候,才会去发送SELECT语句,我们把这种方式叫做延迟加载(lazy-load)/ 懒加载
6.1:如果对象没有被加载过,则会发送一条SELECT语句,去加载对象,再返回属性值
6.2:load方法返回的对象永远不可能为空,所以不能使用if-null来判断。为什么load方法返回的对象永远不为null,即使OID不存在,在load方法执行的方法,根据不会发生SELECT的SQL语句,也就不知道查询结果是否为空,就索性返回一个不为空的对象。如果当前查询的OID在数据库存在,就把数据封装到该对象中,如果当前查询的OID不在数据库中,此时就立刻报错
6.3:load原理
6.3.1:Hibernate框架的中的javassist组件创建了代理类及对象
6.3.2:该对象提供了非主键属性的getter方法和toString方法,感觉上代理对象和真实对象是一样的
6.3.3:该对象存在是否加载完毕的状态,访问属性是先判断对象是否加载完毕,如是直接返回该属性,否则发送SQL查询该对象
二、持久化对象生命周期
1、状态
问题1:主键生成策略不同,save操作时发生INSERT语句的时机不同
- native:执行save方法的时候就立刻发送INSERT语句
- increment:执行save方法的时候没有发送INSERT语句,而是在提交事务时发送
问题2:删除对象的时候,没有立刻发送DELETE语句,而是在提交事务的时候发送的
问题3:为什么在事务环境下,通过get方法得到的对象,只要修改了属性值,才会发生UPDATE语句
总结:执行session中的方法和SQL的发送没有关系,session中的方法仅仅和对象的状态有关系
2、对象的四种状态
1、临时状态/瞬时态(transient):刚刚用new语句创建,没有被持久化(save),不处于session中。特点:没有OID,不在session缓存中
2、持久化状态(persistent):已经被持久化,加入到session的缓存中。特点:有oid,在session的一级缓存中
3、脱管状态/游离状态(detached):已经被持久化,但不处于session中。特点:有oid,不在session中
4、删除状态(removed):对象有关联的ID,并且在session管理下,但是已经计划被删除。特点:有oid,在session缓存中,最终被删除
状态一:临时状态
- new语句刚创建了一个对象
- 删除状态的对象,在事务提交之后,对象处于临时状态
状态二:删除状态
- 持久化状态和游离状态对象执行delete()
状态三:持久化状态
- save方法把临时状态转换为持久化状态
- save方法把游离对象变成另一个持久化状态.
状态四:游离状态
- session.close()方法把所有的持久化对象变成游离对象.
- session.clear()方法把所有持久化对象变成游离对象.
- session.evivt(Object)方法把制定的持久化对象变成游离对象.
-
使用new创建对象,并设置OID(数据库存在该ID);
三、对象状态总结
问题1: 主键生成策略不同,save操作时发送INSERT语句的时机不同.
native:执行save方法的时候就立刻发送INSERT语句.
increment:执行save方法的时候没有发送INSERT语句,而是在提交事务时发送.
临时状态--->持久化状态:从没有OID变的有OID了,过程中会想尽方式获取一个OID值并设置在对象上.
native方式,是数据库自增的方式,只有执行INSERT语句,才能获取自动生成的主键(OID).
increment方式:是Hibernate的自增方式,会先发送SELECT MAX(主键) FROM 表,递增1之后,
就是这一次保存的OID值.此时不需要执行INSERT语句,就可以获取OID,所以并没有立刻发送INSERT语句.
INSERT语句是提交事务的时候,才发送的.
问题2: 删除对象的时候,没有立刻发生DELETE语句,而是在提交事务的时候发送的.
因为delete方法仅仅表示把游离状态对象/持久化状态对象变成删除状态,不负责发送SQL.
问题3: 为什么在事务环境下,通过get方法得到的对象,只要修改了非IOD属性值,会发生UPDATE语句.
引入一级缓存的快照区.
当把通过get方法查询出一个对象的时候,该对象同时存储在一级缓存中,也同时存储在session的快照区.
在通过修改了对象的非IOD属性.(p.setName(“XXX”)),此时就把一级缓存中数据改变了.
默认情况下,在事物提交的时候,就会去检查一级缓存中数据和快照区数据是否一致,如果不一致,
就发送UPDATE语句把一级缓存中的数据同步到数据库.
四、发送SQL的时机
默认情况下,在事务提交时,会自动去数据库同步这一次对象变化对应的SQL,事务提交的时候,发送什么SQL?
- 临时状态-->持久化状态:发送INSERT.
- 持久化状态/游离状态--->删除状态:发送DELETE.
- 游离状态-->持久化状态:发送SQL
- 脏的持久化对象同步到数据库.(session快照)
- session.flush()方法可以手动同步数据库.
总结:由session的持久化方法修改对象的状态,在同步session数据的时候(默认是提交事务,也可以是flush),session再同步脏数据到数据库,完成内存对象和数据库的同步。
session中的方法只负责改变对象的状态,事务负责同步数据