1:Session 概述
Session 接口是 Hibernate 向应用程序提供的操纵数据库的最主要的接口, 它提供了基本的保存, 更新, 删除和加载 Java 对象的方法.
Session 具有一个缓存, 位于缓存中的对象称为持久化对象, 它和数据库中的相关记录对应. Session 能够在某些时间点, 按照缓存中对象的变化来执行相关的 SQL 语句, 来同步更新数据库, 这一过程被称为刷新缓存(flush)
站在持久化的角度, Hibernate 把对象分为 4 种状态: 持久化状态, 临时状态, 游离状态, 删除状态. Session 的特定方法能使对象从一个状态转换到另一个状态.
在 Session 接口的实现中包含一系列的 Java 集合, 这些 Java 集合构成了 Session 缓存. 只要 Session 实例没有结束生命周期, 且没有清理缓存,则存放在它缓存中的对象也不会结束生命周期
Session 缓存可减少 Hibernate 应用程序访问数据库的频率。:
2:flush 缓存:
flush:Session 按照缓存中对象的属性变化来同步更新数据库
默认情况下 Session 在以下时间点刷新缓存:
显式调用 Session 的 flush() 方法
当应用程序调用 Transaction 的 commit()方法的时, 该方法先 flush ,然后在向数据库提交事务
当应用程序执行一些查询(HQL, Criteria)操作时,如果缓存中持久化对象的属性已经发生了变化,会先 flush 缓存,以保证查询结果能够反映持久化对象的最新状态
flush 缓存的例外情况: 如果对象使用 native 生成器生成 OID, 那么当调用 Session 的 save() 方法保存对象时, 会立即执行向数据库插入该实体的 insert 语句.
commit() 和 flush() 方法的区别:flush 执行一系列 sql 语句,但不提交事务;commit 方法先调用flush() 方法,然后提交事务. 意味着提交事务意味着对数据库操作永久保存下来。
* 2:flush方法可能会发送sql语句 不会提交事物
* 3:注意:在未提交事物或显示的调用session.flush()方法之前,也有可能会进行flush操作
* 1>执行HQL或QBC查询,会先进行flush()操作,以得到数据表的最新数据
* 2>若记录的ID是由底层,数据库使用自增的方式生成的,则在调用save()方法后,就会立即发送insert
* .因为save方法后,必须保证对象的id是存在的。oracle不是,因为oracle有序列
//第二条get方法不会再去查数据库,会直接从session中获取
News news = (News)session.get(News.class,1);
System.out.println(news);
News news2 = (News)session.get(News.class,1);
System.out.println(news2);
//1>执行HQL或QBC查询,会先进行flush()操作,以得到数据表的最新数据,即会执行update操作
News news = (News)session.get(News.class, 1);
news.setAuthor("TestCui00");
News news00 = (News)session.createCriteria(News.class).uniqueResult();
System.out.println(news00);
//refresh,会强制发送select语句,以使Session缓存中的对象状态和数据表中的对应的记录保持一致
News news = (News)session.get(News.class, 21);
System.out.println(news);
session.refresh(news);
System.out.println(news);
//清理缓存后,hibernate还需要在查询一次数据库
News news = (News)session.get(News.class, 21);
System.out.println(news);
session.clear();
//清理缓存后,hibernate还需要在查询一次数据库
news = (News)session.get(News.class, 21);
System.out.println(news);
3:在 Hibernate 中设置隔离级别
JDBC 数据库连接使用数据库系统默认的隔离级别. 在 Hibernate 的配置文件中可以显式的设置隔离级别. 每一个隔离级别都对应一个整数:
1. READ UNCOMMITED
2. READ COMMITED
4. REPEATABLE READ
8. SERIALIZEABLE
Hibernate 通过为 Hibernate 映射文件指定 hibernate.connection.isolation 属性来设置事务的隔离级别
4:持久化对象的状态
站在持久化的角度, Hibernate 把对象分为 4 种状态: 持久化状态, 临时状态, 游离状态, 删除状态. Session 的特定方法能使对象从一个状态转换到另一个状态.
持久化对象的状态:
临时对象(Transient):
在使用代理主键的情况下, OID 通常为 null
不处于 Session 的缓存中
在数据库中没有对应的记录
持久化对象(也叫”托管”)(Persist):
OID 不为 null
位于 Session 缓存中
若在数据库中已经有和其对应的记录, 持久化对象和数据库中的相关记录对应
Session 在 flush 缓存时, 会根据持久化对象的属性变化, 来同步更新数据库
在同一个 Session 实例的缓存中, 数据库表中的每条记录只对应唯一的持久化对象
删除对象(Removed)
在数据库中没有和其 OID 对应的记录
不再处于 Session 缓存中
一般情况下, 应用程序不该再使用被删除的对象
游离对象(也叫”脱管”) (Detached):
OID 不为 null
不再处于 Session 缓存中
一般情况需下, 游离对象是由持久化对象转变过来的, 因此在数据库中可能还存在与它对应的记录
5:对象转化状态涉及的接口
Session 的 save() 方法:
Session 的 save() 方法使一个临时对象转变为持久化对象
Session 的 save() 方法完成以下操作:
把 News 对象加入到 Session 缓存中, 使它进入持久化状态
选用映射文件指定的标识符生成器, 为持久化对象分配唯一的 OID. 在 使用代理主键的情况下, setId() 方法为 News 对象设置 OID 使无效的.
计划执行一条 insert 语句:在 flush 缓存的时候
Hibernate 通过持久化对象的 OID 来维持它和数据库相关记录的对应关系. 当 News 对象处于持久化状态时, 不允许程序随意修改它的 ID
persist() 和 save() 区别:
区别:
当数据库中不存在与 OID 对应的记录时, load() 方法抛出 ObjectNotFoundException 异常, 而 get() 方法返回 null
若希望 Session 仅当修改了 News 对象的属性时, 才执行 update() 语句, 可以把映射文件中 <class> 元素的 select-before-update 设为 true. 该属性的默认值为 false
当 update() 方法关联一个游离对象时, 如果在 Session 的缓存中已经存在相同 OID 的持久化对象, 会抛出异常
判定对象为临时对象的标准
Java 对象的 OID 为 null
Session 的 delete() 方法处理过程
计划执行一条 delete 语句
把对象从 Session 缓存中删除, 该对象进入删除状态.
Session 的 doWork(Work) 方法用于执行 Work 对象指定的操作, 即调用 Work 对象的 execute() 方法. Session 会把当前使用的数据库连接传递给 execute() 方法.
Session 接口是 Hibernate 向应用程序提供的操纵数据库的最主要的接口, 它提供了基本的保存, 更新, 删除和加载 Java 对象的方法.
Session 具有一个缓存, 位于缓存中的对象称为持久化对象, 它和数据库中的相关记录对应. Session 能够在某些时间点, 按照缓存中对象的变化来执行相关的 SQL 语句, 来同步更新数据库, 这一过程被称为刷新缓存(flush)
站在持久化的角度, Hibernate 把对象分为 4 种状态: 持久化状态, 临时状态, 游离状态, 删除状态. Session 的特定方法能使对象从一个状态转换到另一个状态.
在 Session 接口的实现中包含一系列的 Java 集合, 这些 Java 集合构成了 Session 缓存. 只要 Session 实例没有结束生命周期, 且没有清理缓存,则存放在它缓存中的对象也不会结束生命周期
Session 缓存可减少 Hibernate 应用程序访问数据库的频率。:
2:flush 缓存:
flush:Session 按照缓存中对象的属性变化来同步更新数据库
默认情况下 Session 在以下时间点刷新缓存:
显式调用 Session 的 flush() 方法
当应用程序调用 Transaction 的 commit()方法的时, 该方法先 flush ,然后在向数据库提交事务
当应用程序执行一些查询(HQL, Criteria)操作时,如果缓存中持久化对象的属性已经发生了变化,会先 flush 缓存,以保证查询结果能够反映持久化对象的最新状态
flush 缓存的例外情况: 如果对象使用 native 生成器生成 OID, 那么当调用 Session 的 save() 方法保存对象时, 会立即执行向数据库插入该实体的 insert 语句.
commit() 和 flush() 方法的区别:flush 执行一系列 sql 语句,但不提交事务;commit 方法先调用flush() 方法,然后提交事务. 意味着提交事务意味着对数据库操作永久保存下来。
Flush使数据表中的记录和Session缓存中的对象的状态保持一致,为了保持一致则可能发送对应的sql
* 1:调用session的commit方法 要先进行flush 在进行提交事物* 2:flush方法可能会发送sql语句 不会提交事物
* 3:注意:在未提交事物或显示的调用session.flush()方法之前,也有可能会进行flush操作
* 1>执行HQL或QBC查询,会先进行flush()操作,以得到数据表的最新数据
* 2>若记录的ID是由底层,数据库使用自增的方式生成的,则在调用save()方法后,就会立即发送insert
* .因为save方法后,必须保证对象的id是存在的。oracle不是,因为oracle有序列
//第二条get方法不会再去查数据库,会直接从session中获取
News news = (News)session.get(News.class,1);
System.out.println(news);
News news2 = (News)session.get(News.class,1);
System.out.println(news2);
//1>执行HQL或QBC查询,会先进行flush()操作,以得到数据表的最新数据,即会执行update操作
News news = (News)session.get(News.class, 1);
news.setAuthor("TestCui00");
News news00 = (News)session.createCriteria(News.class).uniqueResult();
System.out.println(news00);
//refresh,会强制发送select语句,以使Session缓存中的对象状态和数据表中的对应的记录保持一致
News news = (News)session.get(News.class, 21);
System.out.println(news);
session.refresh(news);
System.out.println(news);
//清理缓存后,hibernate还需要在查询一次数据库
News news = (News)session.get(News.class, 21);
System.out.println(news);
session.clear();
//清理缓存后,hibernate还需要在查询一次数据库
news = (News)session.get(News.class, 21);
System.out.println(news);
3:在 Hibernate 中设置隔离级别
JDBC 数据库连接使用数据库系统默认的隔离级别. 在 Hibernate 的配置文件中可以显式的设置隔离级别. 每一个隔离级别都对应一个整数:
1. READ UNCOMMITED
2. READ COMMITED
4. REPEATABLE READ
8. SERIALIZEABLE
Hibernate 通过为 Hibernate 映射文件指定 hibernate.connection.isolation 属性来设置事务的隔离级别
4:持久化对象的状态
站在持久化的角度, Hibernate 把对象分为 4 种状态: 持久化状态, 临时状态, 游离状态, 删除状态. Session 的特定方法能使对象从一个状态转换到另一个状态.
持久化对象的状态:
临时对象(Transient):
在使用代理主键的情况下, OID 通常为 null
不处于 Session 的缓存中
在数据库中没有对应的记录
持久化对象(也叫”托管”)(Persist):
OID 不为 null
位于 Session 缓存中
若在数据库中已经有和其对应的记录, 持久化对象和数据库中的相关记录对应
Session 在 flush 缓存时, 会根据持久化对象的属性变化, 来同步更新数据库
在同一个 Session 实例的缓存中, 数据库表中的每条记录只对应唯一的持久化对象
删除对象(Removed)
在数据库中没有和其 OID 对应的记录
不再处于 Session 缓存中
一般情况下, 应用程序不该再使用被删除的对象
游离对象(也叫”脱管”) (Detached):
OID 不为 null
不再处于 Session 缓存中
一般情况需下, 游离对象是由持久化对象转变过来的, 因此在数据库中可能还存在与它对应的记录
5:对象转化状态涉及的接口
Session 的 save() 方法:
Session 的 save() 方法使一个临时对象转变为持久化对象
Session 的 save() 方法完成以下操作:
把 News 对象加入到 Session 缓存中, 使它进入持久化状态
选用映射文件指定的标识符生成器, 为持久化对象分配唯一的 OID. 在 使用代理主键的情况下, setId() 方法为 News 对象设置 OID 使无效的.
计划执行一条 insert 语句:在 flush 缓存的时候
Hibernate 通过持久化对象的 OID 来维持它和数据库相关记录的对应关系. 当 News 对象处于持久化状态时, 不允许程序随意修改它的 ID
persist() 和 save() 区别:
当对一个 OID 不为 Null 的对象执行 save() 方法时, 会把该对象以一个新的 oid 保存到数据库中; 但执行 persist() 方法时会抛出一个异常.
/**
* persist和save的区别: 在调用persist方法之前,若对象已经有id,则不会执行insert,而会抛出一个异常 /
* /* 1:save方法, 1>使一个临时对象转变为持久化对象 2>为对象分配Id 3>在flush缓存时会发送一条insert语句 4>在save方法之前的id是无效的 5>持久化对象的id是不能被修改的
* */
@Test
public void testmyPersist()
{
News news = new News(1999, "TestZq", "test", new Date(new java.util.Date().getTime()));
session.persist(news);
System.out.println(news);
}
@Test
public void testMySave()
{
News news = new News(100, "TestA", "test", new Date(new java.util.Date().getTime()));
System.out.println(news);
// [id=null, title=Test, author=test, newsDate=2015-10-21]
session.save(news);
System.out.println(news);
// [id=23, title=Test, author=test, newsDate=2015-10-21]
news.setId(13444);
}
Session 的 get() 和 load() 方法
都可以根据跟定的 OID 从数据库中加载一个持久化对象
区别:
当数据库中不存在与 OID 对应的记录时, load() 方法抛出 ObjectNotFoundException 异常, 而 get() 方法返回 null
两者采用不同的延迟检索策略:load 方法支持延迟加载策略。而 get 不支持。
// get和lode的区别,
// 1:执行get方法会立即加载对象,执行lode方法 若不使用该对象,则不会立即执行查询操作,
// 而返回一个代理对象(com.cgc.hibernate.test.News_$$_javassist_0).也就是说 get是立即检索,lode是延迟检索
// 2:lode可能会抛出LazyInitializationException异常,导致异常发生原因是在需要初始化代理对象之前已经关闭的Session
// 3:若数据表中没有对应的记录 且Session也没有被关闭,同时需要使用对象时,get返回null,lode若不使用该对象的任何属性 不出现异常,若需要初始化
// 则抛出一个异常(org.hibernate.ObjectNotFoundException: No row with the given identifier exists:
// [com.cgc.hibernate.test.News#1])
@Test
public void testmyLode()
{
News news = (News)session.load(News.class, 1);
System.out.println(news.getClass().getName());
// session.close();
System.out.println(news);
}
@Test
public void testmyGet()
{
News news = (News)session.get(News.class, 21);
// session.close();
System.out.println(news);
}
Session 的 update() 方法
Session 的 update() 方法使一个游离对象转变为持久化对象, 并且计划执行一条 update 语句.
若希望 Session 仅当修改了 News 对象的属性时, 才执行 update() 语句, 可以把映射文件中 <class> 元素的 select-before-update 设为 true. 该属性的默认值为 false
当 update() 方法关联一个游离对象时, 如果在 Session 的缓存中已经存在相同 OID 的持久化对象, 会抛出异常
当 update() 方法关联一个游离对象时, 如果在数据库中不存在相应的记录, 也会抛出异常.
/**
* <一句话功能简述> <功能详细描述>
*
* @see [类、类#方法、类#成员] update: 1:若更新一个持久化对象,不需要显示的调用session的update方法,因为在调用Transaction的commit方法时 会先执行session的flush方法
* 2:更新为一个游离的对象 需要显示的使用session的update方法,可以把一个游离的对象变为持久化对象
*
* 需要注意的是: 1>无论要更新的游离的对象和数据表的记录是否一致,都会发送update语句
* 那么如何才能让update方法不再盲目的触发update语句,在.hbm.xml文件中设置select-before-update="true", <class name="News" table="NEWS"
* select-before-update="true" dynamic-insert="true"> 但通常不需要设置该属性 即在更新前先查一把 2>若数据表,没有对应的记录 但还调用了update方法,会抛出异常。
* 3>当update()方法关联一个游离对象时,如果Session的缓存中已经存在相同OID的持久化对象,会抛异常 //因为在session中不能有两个OID相同的对象
*/
@Test
public void testmyUpdate()
{
News news = (News)session.get(News.class, 21);
transaction.commit();
session.close();
// news.setId(2345);
session = sessionFactory.openSession();
transaction = session.beginTransaction();
// 当update()方法关联一个游离对象时,如果Session的缓存中已经存在相同OID的持久化对象,会抛异常
// 因为在session中不能有两个OID相同的对象
// News news00 = (News)session.get(News.class, 21);
// 此时的news已经是一个游离的对象
// news.setAuthor("XXXX");
// 更新为一个游离的对象 需要显示的使用session的update方法,可以把一个游离的对象变为持久化对象
session.update(news);
}
Session 的 saveOrUpdate() 方法
Session 的 saveOrUpdate() 方法同时包含了 save() 与 update() 方法的功能
判定对象为临时对象的标准
Java 对象的 OID 为 null
映射文件中为 <id> 设置了 unsaved-value 属性, 并且 Java 对象的 OID 取值与这个 unsaved-value 属性值匹配
/**
* <一句话功能简述>游离的对象执行update方法,临时的对象执行save方法 <功能详细描述>
*
* @see [类、类#方法、类#成员] 1:若OID不为null,但数据表中还没有和其对应的记录会抛异常StaleStateException
* 2:了解:若OID值等于unsaved-value属性值的对象,也会被认为是一个游离对象
*/
@Test
public void testmySaveorUpdate()
{
News news = new News("KKK", "fff", new Date(new java.util.Date().getTime()));
news.setId(1);
session.saveOrUpdate(news);
}
Session 的 delete() 方法
Session 的 delete() 方法既可以删除一个游离对象, 也可以删除一个持久化对象
Session 的 delete() 方法处理过程
计划执行一条 delete 语句
把对象从 Session 缓存中删除, 该对象进入删除状态.
Hibernate 的 cfg.xml 配置文件中有一个 hibernate.use_identifier_rollback 属性, 其默认值为 false, 若把它设为 true, 将改变 delete() 方法的运行行为: delete() 方法会把持久化对象或游离对象的 OID 设置为 null, 使它们变为临时对象
/**
* <一句话功能简述> <功能详细描述>
*
* @see [类、类#方法、类#成员] delete 执行删除操作,只要OID和数据表中的一条记录对应,就会准备执行delete操作 若OID在数据表中没有记录 则抛出异常
*/
@Test
public void testDelete()
{
// 游离对象
// News news = new News();
// news.setId(21);
// news.setTitle("test");
// 持久化对象
News news = (News)session.get(News.class, 24);
session.delete(news);
// 删除并不是立即删除,还没commit,并且调用删除对象 其值还有id值存在,可以设置
// 一个配置属性在.cfg.xml文件中设置<property name="use_identifier_rollback">true</property>
// 则返回值没有id了
System.out.println(news);
}
Session的evict方法:
/**
* <一句话功能简述> <功能详细描述>
*
* @see [类、类#方法、类#成员] evict从session缓存中把指定的持久化对象移除
*/
@Test
public void testEvict()
{
News news00 = (News)session.get(News.class, 29);
News news01 = (News)session.get(News.class, 30);
news00.setAuthor("WW");
news01.setAuthor("WW");
session.evict(news01);
}
通过 Hibernate 调用存储过程
Work 接口: 直接通过 JDBC API 来访问数据库的操作
Session 的 doWork(Work) 方法用于执行 Work 对象指定的操作, 即调用 Work 对象的 execute() 方法. Session 会把当前使用的数据库连接传递给 execute() 方法.