①.对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
②.Hibernate 是一个基于JDBC的主流持久化框架,是一个优秀的ORM 实现。他很大程度的简化DAO层的编码工作
③.hibernate 的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。
(1)hibernate支持两个级别的缓存,默认只支持一级缓存;
(2)每个Session内部自带一个一级缓存;
(3)某个Session被关闭时,其对应的一级缓存自动清除;
(1) 二级缓存独立于session,默认不开启;
Integer是对象. code=null; 对象可以为空.
int 是普通类型, 不可能=null.
因为HQL是面向对象的,而对象类的名称和属性都是大小写敏感的,所以HQL是大小写敏感的。HQL语句:from Cat as cat where cat.id > 1;与from Cat as cat where cat.ID > 1;是不一样的,这点与SQL不同。
from Cat,该句返回Cat对象实例,开发人员也可以给其加上别名,eg. from Cat as cat,对于多表查询的情况,可参考如下:from Cat as cat, Dog as dog其它方面都与SQL类似,在此不再赘述。
①必须提供无参数public构造器
②所有属性private,提供public的getter和setter方法
③必须提供标识属性,与数据表中主键对应,例如Customer类 id属性
④PO类属性应尽量使用基本数据类型的包装类型(区分空值) 例如int---Integer long---Long
⑤不要用final修饰(将无法生成代理对象进行优化)
// 获得Session
Session session =HibernateUtils.openSession();
// 开启事务
Transaction transaction = session.beginTransaction();
Book book =newBook();// 瞬时态(没有OID,未与Session关联)
book.setName("hibernate精通");
book.setPrice(56d);
session.save(book);// 持久态(具有OID,与Session关联)
// 提交事务,关闭Session
transaction.commit();
session.close();
System.out.println(book.getId());// 脱管态(具有 OID,与Session断开关联)
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JDBCTransactionFactory
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JDBCTransactionFactory
Session session = sf.openSession();
Transaction tx = session.beginTransactioin();
...
session.flush();
tx.commit();
session.close();
net.sf.hibernate.transaction.JDBCTransaction:
public void begin() throws HibernateException {
...
if (toggleAutoCommit) session.connection().setAutoCommit(false);
...
}
public void commit() throws HibernateException {
...
try {
if ( session.getFlushMode()!=FlushMode.NEVER ) session.flush();
try {
session.connection().commit();
committed = true;
}
...
toggleAutoCommit();
}
Connection conn = ...; <--- session = sf.openSession();
conn.setAutoCommit(false); <--- tx = session.beginTransactioin();
... <--- ...
conn.commit(); <--- tx.commit(); (对应左边的两句)
conn.setAutoCommit(true);
conn.close(); <--- session.close();
//方式一
:去
src
读取
hibernate
.
properties
属性配置文件
Configuration cfg =newConfiguration();
//方式二:去src读取 hibernate.cfg.xml
Configuration cfg =newConfiguration().configure();
Configuration cfg =newConfiguration().configure("自定义xml文件");去src 加载指定文件
org.hibernate.MappingException:Unknown entity: cn.itcast.domain.Customer
//方式一:
configuration.addResource("cn/itcast/domain/Customer.hbm.xml");加载hbm文件
//方式二:
configuration.addClass(Customer.class);加载Class,自动搜索hbm映射文件
//预定义SQL语句
name="login">
save 完成插入
update 完成修改
delete完成删除
get/load 根据主键字段查询
createQuery、 createSQLQuery 创建查询对象Query接收HQL,SQLQuery接收SQL
createCriteria() 面向对象条件查询
//默认false
false 事务不提交
name="hibernate.connection.autocommit">true 事务提交
开发代码步骤
获得HibernateSession对象
编写HQL语句
调用session.createQuery 创建查询对象
如果HQL语句包含参数,则调用Query的setXXX设置参数
调用Query对象的list()或uniqueResult()方法执行查询
*private transient ActionQueue actionQueue; ----行动队列(标记数据活动)
*private transient StatefulPersistenceContext persistenceContext;----持久化上下文
Book book =(Book) session.get(Book.class,1);// 第一次查询,缓存中没有
System.out.println(book);
Book book2 =(Book) session.get(Book.class,1);// 因为第一次查询,对象已经被放入1级缓存,不会查询数据
System.out.println(book2);
*生成一条SQL语句,返回同一个对象,第一次查询生成SQL,查询对象,将对象放入一级缓存,第二次查询,直接从一级缓存获得
* 测试快照区的使用
*/
@Test
publicvoid demo3(){
// 获得Session
Session session =HibernateUtils.openSession();
// 开启事务
Transaction transaction = session.beginTransaction();
// 查询id 为1 的图书对象
Book book =(Book) session.get(Book.class,1);// 第一次查询,将对象加入一级缓存
System.out.println(book);
book.setName("深入浅出Hibernate技术");// 修改书名(一级缓存被修改,自动update)
// 没有手动执行update,因为快照区原因,自动更新
// 提交事务,关闭Session
transaction.commit();
session.close();
@Test
// Session 对于 一级缓存操作
publicvoid demo4(){
// 获得Session
Session session =HibernateUtils.openSession();
// 开启事务
Transaction transaction = session.beginTransaction();
// 查询id 为1 的图书对象
Book book =(Book) session.get(Book.class,1);// 第一次查询,将对象加入一级缓存
System.out.println(book);
// book.setPrice(80d); // 修改一级缓存数据
// 将缓存内容同步到数据库
// session.flush();
// 清除一级缓存所有数据
// session.clear();
// 清除一级缓存中 指定对象
// session.evict(book);
book.setPrice(30d);// 一级缓存改变
session.refresh(book);// 用数据库内容 覆盖快照区和一级缓存
// 提交事务,关闭Session
transaction.commit();
session.close();
}
@Test
// 理解 FlushMode作用
publicvoid demo5(){
// 获得Session
Session session =HibernateUtils.openSession();
// 设置 flushMode
session.setFlushMode(FlushMode.MANUAL);
// 开启事务
Transaction transaction = session.beginTransaction();
// 查询id 为1 的图书对象
Book book =(Book) session.get(Book.class,1);// 第一次查询,将对象加入一级缓存
System.out.println(book);
book.setPrice(1000d);// 修改价格
session.createQuery("from Book").list();// 查询所有图书 (AUTO 级别 flush)
// 提交事务,关闭Session
transaction.commit();// (COMMIT 级别 flush)
// session.flush(); // MANUAL 级别 flush
session.close();
}
@Test
// 脱管对象更新
publicvoid demo6(){
// 获得Session
Session session =HibernateUtils.openSession();
// 开启事务
Transaction transaction = session.beginTransaction();
Book book =newBook();// 瞬时
book.setId(1);// 脱管
book.setName("java入门");
book.setPrice(40d);
session.update(book);// 持久
session.flush();
// book.setPrice(50d);
// 提交事务,关闭Session
transaction.commit();
session.close();
}
name="cn.itcast.domain.firstcache.Book"table="book"catalog="hibernate3day2"select-before-update="true">
@Test
// 一级缓存 存在两个相同OID 持久态对象 报错
publicvoid demo7(){
// 获得Session
Session session =HibernateUtils.openSession();
// 开启事务
Transaction transaction = session.beginTransaction();
// 查询
// Book b = (Book) session.get(Book.class, 1); // 持久
Book book =newBook();// 瞬时
book.setId(1);// 脱管
book.setName("java入门");
book.setPrice(50d);
session.update(book);// 持久
// 提交事务,关闭Session
transaction.commit();
session.close();
}
@Test
// PO对象,OID为 hbm文件 配置 unsaved-value 也是瞬时对象, saveOrUpdate 执行 save操作
publicvoid demo8(){
// 获得Session
Session session =HibernateUtils.openSession();
// 开启事务
Transaction transaction = session.beginTransaction();
Book book =newBook();// 瞬时
book.setId(-1);// 存在OID , -1是unsaved-value 也是瞬时
book.setName("xxx");
book.setPrice(100d);
session.saveOrUpdate(book);
// 提交事务,关闭Session
transaction.commit();
session.close();
}
缓存好处: 将数据库或者硬盘数据,保存在内存中,减少数据库查询次数,减少硬盘交互,提高检索效率
hibernate 共有两个级别的缓存
* 一级缓存,保存Session中, 事务范围的缓存
* 二级缓存,保存SessionFactory ,进程范围的缓存
SessionFacoty 两部分缓存
内置 :Hibernate 自带的, 不可卸载. 通常在 Hibernate 的初始化阶段, Hibernate 会把映射元数据和预定义的 SQL 语句放到SessionFactory 的缓存中, 映射元数据是映射文件中数据的复制, 而预定义 SQL 语句时 Hibernate 根据映射元数据推到出来的. 该内置缓存是只读的.
外置 :一个可配置的缓存插件. 在默认情况下, SessionFactory 不会启用这个缓存插件. 外置缓存中的数据是数据库数据的复制, 外置缓存的物理介质可以是内存或硬盘,必须引入第三方缓存插件才能使用。
** 一级缓存的操作会同步到二级缓存
更新时间戳区域
作用:记录数据最后更新时间,确保缓存数据是有效的
Hibernate 提供了和查询相关的缓存区域:
* 二级缓存缓存数据都是类对象数据,数据都是缓存在 "类缓存区域" ,二级缓存缓存PO类对象,条件(key)是id
查询缓存适用场合:
**应用程序运行时经常使用查询语句
**很少对与查询语句检索到的数据进行插入, 删除和更新操作
如果查询条件不是id查询, 缓存数据不是PO类完整对象 =====> 不适合使用二级缓存
查询缓存: 缓存的是查询数据结果, key是查询生成SQL语句 , 查询缓存比二级缓存功能更加强大
2)启用查询缓存 hibernate.cfg.xml
name="hibernate.cache.use_query_cache">true
query.setCacheable(true);
transactional : 提供Repeatable Read事务隔离级别,缓存支持事务,发生异常的时候,缓存也能够回滚
read-write : 提供Read Committed事务隔离级别,更新缓存的时候会锁定缓存中的数据
nonstrict-read-write :导致脏读, 很少使用
read-only : 数据不允许修改,只能查询
* 很少被修改,不是很重要,允许偶尔的并发问题, 适合放入二级缓存。考虑因素(二级缓存的监控【后面学习】,它是是否采用二级缓存主要参考指标)