本文主要是介绍Hibernate3入门之第二章一级缓存和持久化类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Hibernate3入门之第二章一级缓存和持久化类
上节课程回顾
-
Hibernate快速入门:
-
下载Hibernate开发包.
-
Hibernate开发包目录结构:
-
文档:
-
开发包:
-
操作字节码:
-
必须的
-
可选的
-
jpa
-
-
项目:
-
-
创建一个java项目导入相应jar包.
-
创建数据库表:
-
创建一个实体类:
-
建立映射:
-
创建Hibernate核心配置文件:
-
编写一个测试类:
-
-
Hibenrate的CRUD的操作:
-
save(); / update(); / delete(); / get()/load();
-
get()/load()的区别
get :采用是立即检索,马上发送SQL查询.返回的是真实对象.检索一个找不到的对象的时候NullPointException
load :采用延迟加载技术,当真正使用这个对象的时候,才会发送SQL.返回代理对象.检索一个找不到的对象的时候ObjectNotFoundException
-
-
Hibernate的常见配置及API:
-
核心配置:两种方式;
-
属性文件的方式:
在src下创建一个hibernate.properties.。手动加载映射文件.
-
XML格式的配置:
在src下创建一个hibernate.cfg.xml
-
必须的配置:
数据库连接信息.。 Hibernate的方言.
-
可选配置
显示SQL。格式化SQL。hbm2ddl.auto(create/create-drop/update/validate)
-
-
映射配置:
-
<class>建立类与表映射
name :类的全路径.。table :表名称
-
<id>
name。column。type。length
-
<property>
name。column。type。length
-
-
-
Hibernate的API
-
Configuration:管理配置信息.
属性文件---->直接创建.
XML---------->new Configuration().configure();
-
SessionFactory:
维护二级缓存,线程安全的对象
-
Session
维护一级缓存,线程不安全的对象
-
Transaction
事务是默认不自动提交,手动提交事务.
-
Query
-
Criteria
-
-
持久化类编写:
-
持久化类:就是一个实体类 + XML映射.
-
编写原则:
无参数构造:属性提供set/get方法提供为一个标识:尽量使用包装类型:这个类尽量不要使用final修饰.
-
自然主键和代理主键:
-
Hibernate提供主键生成策略:
increment :自动增长.适合 short int long...不是使用数据库的自动增长机制.使用Hibernate框架提供的自动增长方式.select max(id) from 表; 在最大值的基础上+1.(多线程的问题.)在集群下不要使用identity :自动增长.适合 short int long采用数据库的自动增长机制.不适合于Oracle数据库.sequence :序列.适用于 short int long ... 应用在Oracle上 .uuid :适用于字符串类型的主键.采用随机的字符串作为主键.native :本地策略.底层数据库不同.自动选择适用identity 还是 sequence.assigned :Hibernate框架不维护主键,主键由程序自动生成.foreign :主键的外来的.(应用在多表一对一的关系.)
-
Hibernate的持久化类状态
- 持久化类状态
持久化类:就是一个实体类 与 数据库表建立了映射.
Hibernate为了方便管理持久化类,将持久化类分成了三种状态.
状态 | 特点 |
---|---|
Transient瞬时态: | 持久化对象没有唯一标识OID.没有纳入Session的管理 |
Detached脱管态: | 持久化对象有唯一标识OID,没有纳入到Session管理 |
Persistent持久态: | 持久化对象有唯一标识OID.已经纳入到Session的管理. |
同时对于持久态而言:持久化持久态对象有自动更新数据库的能力
- 区分三种持久化对象的状态:
使用代码进行说明
// 关于瞬时态、持久态和托管态的理解public void test1() {Session session = Hibernate3Utils.openSession();Transaction ts = session.beginTransaction();Book book = new Book(); // 瞬时态 没有唯一标识OID 没有与session关联book.setName("Mybitas开发");book.setAuthor("孙XX");book.setPrice(60d);session.save(book);// 持久态 有唯一标识OID 与session关联ts.commit();book.setName("SpringMVC开发");// 托管态 有唯一标识OID 没有与session关联}
-
三种状态对象转换:
-
瞬时态:
获得: Book book = new Book();瞬时--->持久save(book);save()/saveOrUpdate(); 瞬时--->脱管book.setId(1);
-
脱管态:
获得: Book book = new Book(); book.setId(1);脱管--->持久: * session.update(); * update()/saveOrUpdate()/lock()脱管--->瞬时: * book.setId(null);
-
持久态:
获得: Book book = (Book)session.get(Book.class,1);get()/load()/find()/iterate();持久--->瞬时:delete(book);特殊状态:删除态.(被删除的对象,不建议去使用.)持久--->脱管:session.close();close()/clear()/evict();
-
-
持久态对象有自动更新数据库的能力;
// 持久态有自动更新数据库的能力public void test2() {Session session = Hibernate3Utils.openSession();Transaction ts = session.beginTransaction();Book book = (Book) session.get(Book.class, 1);book.setName("SpringMVC开发");// 提交事务时进行更新// session.update(book);//持久态 自动更新数据库不需要更新操作ts.commit();// 利用hibernate的一级缓存,提交事务之后发送sql语句直接更新}
Hibernate的一级缓存
-
什么是缓存:
缓存将数据库/硬盘上文件中数据,放入到缓存中(就是内存中一块空间).当再次使用的使用,可以直接从内存中获取.
-
缓存的好处:
提升程序运行的效率.缓存技术是Hibernate的一个优化的手段.
-
Hibernate分成两个基本的缓存:
一级缓存:Session级别的缓存.一级缓存与session的生命周期一致.自带的.不可卸载.
二级缓存:SessionFactory级别的缓存.不是自带的.
在 Session 接口的实现中包含一系列的 Java 集合, 这些 Java 集合构成了 Session 缓存. 只要 Session 实例没有结束生命周期, 存放在它缓存中的对象也不会结束生命周期.
-
证明Hibernate的一级缓存的存在:
// 证明一级缓存的存在public void test3() {Session session = Hibernate3Utils.openSession();Transaction ts = session.beginTransaction();Book book = new Book();book.setName("SpringBoot开发");book.setAuthor("乔峰");book.setPrice(46d);// 保存之后会将保存图书的id返回Integer id = (Integer) session.save(book);//// 再次取得图书,看书否会发送sql语句Book book1 = (Book) session.get(Book.class, id);//// 当获取图书的时候是不会去发送sql语句的System.out.println(book1);ts.commit();}
当执行session.save(book);之后,程序执行插入(insert)并将数据保存在一级缓存中,所以在session.get(Book.class, id);时不再发送任何SQL语句,直接从一级缓存中获取
-
深入理解一级缓存中快照区:
// 证明一级缓存的快照区public void test4() {Session session = Hibernate3Utils.openSession();Transaction ts = session.beginTransaction();Book book1 = (Book) session.get(Book.class, 1);book1.setName("Hibernate3开发");ts.commit();}
断点调试:在Book book1 = (Book) session.get(Book.class, 1);处设置断点;在Variables窗口处找到
session—>h—>realSession—>persistenceContext–>entityEntries
在entityEntries集合(Map)中存放着一级缓存区(key)和快照区(value)
快照举例说明:
在你很久没有回家以后,当你回到家中你周围的邻居对你有一个印象(快照),当你再次回到家中的时候,你得邻居会,将现在看到你的模样和他们现在看到你的模样进行对比,是否发生了变化。
结论:向一级缓存存入数据的时候,放入一级缓存区和一级缓存快照区,当更新了一级缓存的数据的时候,事务一旦提交,比对一级缓存和快照区,如果数据一致,不更新,如果数据不一致,自动更新数据库.
-
Hibernate管理一级缓存:
一级缓存是与session的生命周期相关的.session生命周期结束,一级缓存销毁了.
方法 描述 clear() 清空一级缓存中所有的对象. evict(Object obj) 清空一级缓存中某个对象. flush() 刷出缓存. refresh(Object obj) 将快照区的数据重新覆盖了一级缓存的数据. 举例说明:
clear()清空缓存区所有数据
evict(指定对象)清空缓存区指定对象的数据public void test5() {Session session = Hibernate3Utils.openSession();Transaction ts = session.beginTransaction();Book book1 = (Book) session.get(Book.class, 1);Book book2 = (Book) session.get(Book.class, 2);System.out.println(book1);System.out.println(book2);// 上面的发送sql语句,下面的不再发送// session.clear();session.evict(book1);Book book4 = (Book) session.get(Book.class, 2);Book book3 = (Book) session.get(Book.class, 1);System.out.println(book1);System.out.println(book2);ts.commit();}
flush()指明发送SQL语句的时机
refresh()在更新之前快照区将一级缓存区数据覆盖public void test6() {Session session = Hibernate3Utils.openSession();Transaction ts = session.beginTransaction();Book book1 = (Book) session.get(Book.class, 1);book1.setName("PHP开发");// session.flush();// 只是发送sql语句而不执行更新// ts.commit();// 执行更新session.refresh(book1);ts.commit();}
-
Hibernate一级缓存的刷出时机
FlushMode:常量:* ALWAYS :每次查询的时候都会刷出.手动调用flush.事务提交的时候.* AUTO :默认值.有些查询会刷出.手动调用flush.事务提交的时候.* COMMIT :在事务提交的时候,手动调用flush的时候.* MANUAL :只有在手动调用flush才会刷出.严格程度:MANUAL > COMMIT > AUTO > ALWAYS
操作持久化对象的方法
-
save():
保存一条记录:将瞬时态对象转成持久态对象.
-
update()
更新一条记录:将脱管态对象转成持久态对象.
为了避免在更新数据时重复发送更新语句,我们在更新之前应该先查询一下
配置属性:
在<class>标签上设置select-before-update="true"在更新之前先去查询
-
saveOrUpdate()
根据对象状态的不同执行不同的save获得update方法.
如果对象是一个瞬时态对象:执行save操作.
如果对象是一个脱管态对象:执行update操作.
置id不存在,就会报错,可以在<id>上设置一个unsaved-value=”-1”,(不一定是-1在setId处是多少就置为多少)执行保存的操作.
-
delete():
将持久态对象转成瞬时态.
-
get()/load():
获得一个持久态对象.
hibernate update 只更新部分字段的3种方法
-
在进行测试时忽然想到,关系update 的一些问题,Hibernate 中如果直接使用Session.update(Object o);或者session.saveOrUpdate(Object o);(由托管态转为持久态时),在使用这两者的时候,会把这个表中的所有字段更新一遍。且没有设置的将置为默认值(null)。
Session session = Hibernate3Utils.openSession();Transaction ts = session.beginTransaction();Book book = new Book();// 托管态book.setId(8);book.setAuthor("孙XX");ts.commit();
发送的更新语句:
Hibernate: updateBOOK setNAME=?,AUTHOR=?,PRICE=? whereID=?
我们可以通过先查询后修改的方式进行只修改部分字段的值
Book book = (Book) session.get(Book.class, 8);book.setName("深度学习");session.saveOrUpdate(book);//session.update(book);
-
同时因为上面的原因,会把所有字段遍历一遍,这样效率会很低。
那么怎么只更改我们更新的字段呢?同时提升效率呢
有三种方式:
-
第一种方式:
1.XML中设置property 标签 update = “false” ,如下:我们设置 age 这个属性在更改中不做更改
<property name="price" type="java.lang.Double" update="false" ><column name="PRICE" /></property>等价<property name="price" update="false"></property>
2.同时在Annotation(注解)中,在属性GET方法上加上@Column(updatable=false)
@Column(updatable = false)public Double getPrice() {return price;}
3.缺点就是不灵活。。。
-
第二种方法
1.使用XML中的 dynamic-update=“true”
<class name="com.syj.vo.Book" table="BOOK" dynamic-update="true">......</class>
2.这样就不需要在字段上设置了。
3.但这样的方法在Annotation中没有
-
第三种方式
1.使用HQL语句(灵活,方便)
public void update(){Session session = HibernateUitl.getSessionFactory().getCurrentSession();session.beginTransaction();Query query = session.createQuery("update Book b set b.name = 'Python' where id = 8");query.executeUpdate();session.getTransaction().commit();}
2.Hibernate 执行的SQL语句:
Hibernate: updateBOOK setNAME='Python' whereID=8
3.这样就只更新了我们更新的字段
-
这篇关于Hibernate3入门之第二章一级缓存和持久化类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!