五、映射基础
1、实体类采用javabean的编写规范
JavaBean编写规范:
a、类一般是public的
b、有默认的构造方法
c、字段都是私有的
d、提供公有的getter和setter方法
e、一般都实现java.io.Serializable接口
注意:hibernate采用的暴力反射
2、基本类型OR包装类型
int ---> Integer
.......
3、访问实体类数据的策略(了解)
通过上面我们可知,hibernate是采用的暴力反射,所以我们既可以通过属性页可以用过字段访问。但是一般都使用属性(即get和set方法)
直接执行会报错,我们需要通过在配置文件中配置,来告知hibernate采用访问属性的方式进行取值和赋值。
1 2 9 1213 14 15 16 17 3318 24 26 2925 30 31 32
4、派生属性
概念:
实体类中的某些属性在数据库表中没有对应的字段,该属性的值是由数据库表中其他字段计算出来的。这样的属性叫做派生属性。
模拟测试数据:
创建一个订单表:
12 3 144 65 7 12 13
5、控制insert和update
映射文件:xml
5.1、property元素(了解)
insert:默认值是true,如果改为false。表示该属性永远不会被插入。(动态生成的SQL语句)
1 2 9 1213 20 21 22 23 5524 40 42 5141 52 53 54
5.2、class元素
mutable:默认值是true,如果为false,表示当前类所有属性都不会被修改。
dynamic-insert:默认是false,如果为true。会动态生成insert语句,只涉及不为null的字段。
dynamic-update:默认值是false。如果为true,会动态生成update语句,只更新数据有变化了的字段。
如果类的属性很多,建立动态生成insert或update。(动态生成SQL消耗的资源可以忽略不计)。
6、避免与数据库关键字冲突的问题
例如:
我们在创建订单表时,有可能会使用Order来作为表名,但是由于order是关键字,可以在order上加入反引号。
六、映射对象标识符
1、概述
总结:应该让Hibernate来管理OID。
2、Hibernate主键生成策略
2.1、如何配置
12 3
2.2、常用生成策略
a、increment
OID必须是long,int,short类型的。
弊端:
适用于单应用访问同一个数据库的场合,在集群环境下不推荐使用。
b、identity
数据库系统必须支持自动增长字段类型
OID必须是long、int、short类型
注意:increment和identity的区别,一个是由Hibernate来负责维护,一个是由数据库来负责维护。
c、hilo:hibernate利用高地位算法生成OID
不依赖底层数据库,适用于所有的数据库。
OID必须是long、int、short类型
该算法生成的标识符只能在一个数据库中保证唯一
1 2 9 1213 20 21 22 23 5524 40 42 5141 52 53 54
算法:
高值*(max_lo+1)+不大于max_lo的值
高值从0开始
0*(5+1)+0=0 忽略
0*(5+1)+1=1
0*(5+1)+2=2
0*(5+1)+3=3
0*(5+1)+4=4
0*(5+1)+5=5 下一个高值为1
1*(5+1)+0=6
1*(5+1)+1=7
1*(5+1)+2=8
1*(5+1)+3=9
1*(5+1)+4=10
1*(5+1)+5=11 下一个高值为2
d、native
依据底层数据库对自动生成标识符的支持能力来选择使用identity、sequence来生成标识符
适合跨数据库平台开发
OID必须是long、int、short类型
七、Session对象的一级缓存
1、Session的一级缓存
1 //证明一级缓存的存在 2 @Test 3 public void test1(){ 4 Session s = HibernateUtil.getSession(); 5 Transaction tx = s.beginTransaction(); 6 Student s1 = s.get(Student.class, 2);//会去数据库查询,同时会把查询出来的数据存入一级缓存之中。 7 System.out.println(s1); 8 Student s2 = s.get(Student.class, 2);//不会去查询,因为一级缓存之中有数据。 9 System.out.println(s2);10 tx.commit();11 s.close();12 }
2、为什么使用缓存
a、减少访问数据库的频率。应用从缓存中读取数据的速度比从数据库获取数据要快,提高了数据的访问性能
b、当缓存中的对象之间存在循环关联关系时,Session保证不会出现访问对象的关联死循环,以及由死循环造成的JVM堆栈溢出问题
c、保证数据库中的相关记录与缓存中的对象保持同步
注意:当与数据库中的数据一致时,不会进行更新。
3、如何做到数据发生变化时进行同步
3.1、快照(SnapShot)机制
1 //修改数据 2 //快照机制 3 @Test 4 public void test2(){ 5 Session s = HibernateUtil.getSession(); 6 Transaction tx = s.beginTransaction(); 7 Student s1 = s.get(Student.class, 2);//会去数据库查询,同时会把查询出来的数据存入一级缓存之中。 8 System.out.println(s1);//gender:male 9 s1.setGender("male");//改gender,其实改的是内存对象10 System.out.println(s1);//gender:female11 tx.commit();12 s.close();//一级缓存在此行执行之后就消失了。13 14 //在此种再接着写代码15 System.out.println(s1);//gender:female16 }
4、控制Session的一级缓存
目的:学习Session中与一级缓存有关的方法。
4.1、Session.clear();:清空缓存。
1 /* 2 * clear方法 3 * 作用:清空一级缓存 4 * 5 * 和close有区别: 6 * close执行之后,一级缓存也没有了。 7 * clear执行完成之后,session是还可以用的。 8 */ 9 @Test10 public void test1(){11 Session s = HibernateUtil.getSession();12 Transaction tx = s.beginTransaction();13 Student s1 = s.get(Student.class, 2);//会去数据库查询,同时会把查询出来的数据存入一级缓存之中。14 System.out.println(s1);15 16 s.clear();17 18 Student s2 = s.get(Student.class, 2);19 System.out.println(s2);20 tx.commit();21 s.close();22 }
4.2、Session.evict(Object entity);:清除一级缓存中指定的实体对象。
1 /* 2 * evict方法 3 * 作用清除的是指定实体的缓存 4 */ 5 @Test 6 public void test2(){ 7 Session s = HibernateUtil.getSession(); 8 Transaction tx = s.beginTransaction(); 9 Student s2 = s.get(Student.class, 2);//会去数据库查询,同时会把查询出来的数据存入一级缓存之中。10 Student s3 = s.get(Student.class, 3);//会去数据库查询,同时会把查询出来的数据存入一级缓存之中。11 12 s.evict(s2);13 14 Student s4 = s.get(Student.class, 2);//会去数据库查询,同时会把查询出来的数据存入一级缓存之中。15 Student s5 = s.get(Student.class, 3);//不会去查询,因为一级缓存之中有数据16 tx.commit();17 s.close();18 }
4.3、Session.refresh(Obect entity);:重新刷新缓存(用数据库中的数据同步缓存中指定的实体)
1 /* 2 * refresh方法 3 * 作用:那数据库的数据,来同步一级缓存。 4 */ 5 @Test 6 public void test3(){ 7 Session s = HibernateUtil.getSession(); 8 Transaction tx = s.beginTransaction(); 9 Student s1 = s.get(Student.class, 6);//会去数据库查询,同时会把查询出来的数据存入一级缓存之中。10 System.out.println(s1);//gender :male11 s1.setGender("female");//修改gender:female12 System.out.println(s1);13 s.refresh(s1);14 System.out.println(s1);15 tx.commit();16 s.close();17 }
4.4、Session.flush();:清理缓存(同步缓存中数据到数据库中),但是不会清空。
a、清理时机:
1、Transaction.commit()时会先清理缓存后提交事务。安排在此处是为了减少数据访问的频率和缩短当前事务对数据库中资源的锁定时间。
2、当应用中执行一些查询操作(Query)时,如果缓存中的对象发生了变化,会先进行清理。从而保证查询出的数据是正确的
3、显式调用Session的flush()方法
1 /* 2 * flush方法 3 * 作用:手动刷新缓存。把数据从session中刷新出去。 4 */ 5 @Test 6 public void test5(){ 7 Session s = HibernateUtil.getSession(); 8 Transaction tx = s.beginTransaction(); 9 Student s1 = s.get(Student.class, 6);//会去数据库查询,同时会把查询出来的数据存入一级缓存之中。10 System.out.println(s1);//gender :male11 s1.setGender("male");//修改gender:female12 System.out.println(s1);13 14 s.flush();//当有此行存在时,此时就会看到update语句15 16 tx.commit();//默认此行刷出缓存中的数据。去拿缓存修改数据库的数据17 s.close();18 }
b、设置清理时机
八、实体对象的状态
1、各种状态图
2、状态说明:(判断对象处于什么状态不以数据库中有无记录作为依据,因为事务的问题,事务是否已经提交)
2.1、临时状态(transient):
用new语句创建,还没有被持久化,并且不在Session的缓存中。
标识:OID为null,没有和Session建立关系。
2.2、持久化状态(persistent):
已经计划被持久化,并且加入到Session的缓存中。(为什么说计划:因为事务问题,是否已经提交事务)
标识:OID不为null,建立了和Session的关系。
2.3、删除状态(removed):
不在Session的缓存中,且Session已经计划将其从数据库中删除。
标识:OID不为null,计划要从Session中删除的。
2.4、游离状态(detached脱管):
已经被持久化,不在Session的缓存中
标识:OID不为null,没有和Session建立关系。