步骤
1.加载hibernate.cfg.xml配置文件 Configuration
2.创建sessionFactory工厂对象
3.创建session接口,线程不安全,获取方法:get()
自动建表:
—————————————————
hibernate.hbm2dll.auto
–none: 默认
–create: 每次都创建新的表
–update: 表不存在就创建,自动修改表字段
对象标识符
———————————————–
OID:区分对象的唯一标识,对应主键
<id>
派生属性:
————————————————-
formula=”(select sum(c.price) from customers c)”
控制insert,update语句
————————————————–
<property insert=”false” : 不能在插入记录时插入数据
<property update=”fasle” : 不能在更新记录时更新数据
<class mutable=”false” : 所有字段不能更新,默认为true
<class dynamic-insert=”true” : 为空的属性不会被生成在insert语句
<class dynamic-update=”true” : 没修改的属性不会被生成在update语句,仅用在修改查询后的结果.
`数据库符号的处理
———————————————
<column name=”`a b`” />
缓存的定义
———————————–
一份拷贝,缓存的物理介质通常是内存
Session的一级缓存
———————————————
session.get():在第一次(一级缓存不存在)查询中从数据库中查询并缓存起来,第二次直接从缓存中查询
Session快照
——————————————————
在事务中查询出来数据后直接修改(必须要修改与原值不相同)再提交事务,能够执行update语句
原理:查询出来的数据的属性值会在Session快照中保存一份,在提交事务的时候会把缓存中的数据(清理,同步到数据库中)与快照的数据比较,变化了就update
generator标识符生成器:
—————————————————————-
increment : max(id)+1 最大值加1 存在线程并发访问的问题
identity : 自动增长,依赖数据库支持
native : 根据数据库底层自动选择合适的生成器,适合跨数据库平台
assigned : 自然主键
映射联合主(外)键
——————————————————————
<composite-id>
<key-property>
<key-property>
四、数据库关联关系
———————————————————————————
一对多单向关联:
在1的一方增加多的一方的关联关系
private Set<多的对象> set = new HashSet(0);
<set name=”属性”>
<key column=”外键” />
<one-to-many class=”属性对象对应的类型” />
</set>
多对一单向关联:
在多的一方增加1的一方的关联关系
private 一的对象;
保存—————-
<many-to-one name=”属性名称” column=”外键名称” />
* 创建多的一方对象->创建一的一方对象->建立多与一的关联关系->保存多->保存一
会执行3条SQL语句
* 创建多的一方对象->创建一的一方对象->建立多与一的关联关系->保存一->保存多
会执行2条SQL语句
* 优化:先保存一的一方再保存多的一方。
查询—————-
* 直接使用get的方法,Hibernate自动执行相应的select语句
异常—————-
* TransientObjectException(只保存多的不保存一的,但已建立关联关系)
临时对象oid为空,对象引用无法保存临时对象
解决办法:级联保存与更新 cascade=”save-update”
多对一双向关联
在1的一方增加多的一方的关联关系
在多的一方增加1的一方的关联关系
上面两种关联关系的并集配置
保存————
* 建立双向关联关系
1.get多.add(多);
多.set1(1);
异常————
* TransientObjectException(保存一的一方不保存多的一方)
临时对象oid为空,对象引用无法保存临时对象
解决办法:级联保存与更新 cascade=”save-update”
查询————
* 延时查询
健壮性———-
* 建立双向关联
多的关联一的
一的关联多的
修改————
* 查询对象
修改对象中的对象
快照更新~
关联关系维护【更新】
* inverse属性,默认false双方都可维护
应该由多的一方维护关联关系
<set inverser=”true” />
* 级联删除
<set cascade=”delete”
* 父子关系
<set cascade=”delete-orphan”
把“孤儿”删除
* 排序
<set order-by=”id desc”
临时对象
—————————————–
在没有执行session的save,update等操作时,所有对象都是临时对象,oid=null
五、操作持久化对象
————————————————————-
java生命周期
Session缓存
* session.flush();
清理缓存、把缓存中的数据同步到数据库,清理但不清空缓存
* tx.commit();
先清理缓存后提交事务
* session.clear();
清空缓存,删除缓存中的数据
* session.refresh(Object);
刷新缓存,把数据库中的数据同步到缓存,获取最新的数据
* 缓存清理3种模式
session.setFlushMode
FlushMode.AUTO:默认,查询与事务提交与session.flush都会清理缓存
FlushMode.COMMIT:只有执行事务commit与session.flush才会清理缓存
FlushMode.NEVER:只有执行session.flush才会清理缓存
插入大数据时先session.flush与session.clear
Session的四种状态
* 临时状态
oid = null
缓存中没有记录
数据库中没有记录
* 持久状态
oid != null
缓存中有记录
与数据库中的相关记录对应
* 游离状态
oid != null
缓存中没有记录 session.close()
有数据库中有记录
* 删除状态
oid != null
从缓存中删除 session.delete(object)
准备从数据库中删除
* 普通 -> new() -> 临时 -> 回收
* 临时 -> save()、saveOrUpdate() -> 持久
* 普通 -> get()、load()、query() -> 持久
* 持久 -> close()、evict() -> 游离
* -> delete -> 删除 -> 回收
* 游离 -> update()、saveOrUpdate() -> 持久 -> 回收
* -> delete() -> 删除 -> 回收
#session.evict(object) 把一个对象变成游离对象
<class select-before-update=”true” 在更新之前查询,如果修改了就更新,否则不
* saveOrUpdate
游离态执行update方法
临时态执行save方法
持久态不执行操作
控制:
undaved-value与oid的值相等则执行save()方法,否则执行update()方法
undaved-value不设置与oid为null时也执行save()方法,否则看上一条
* get()与load()
lazy=false 意即加载(饿汉式)
查找的记录不存在
load()方法会抛异常
get()方法会返回null
lazy=true 延迟加载(懒汉式)
查找的记录存在
load()懒加载模式,使用数据时才发起select语句
get()方法会马上返回记录,不受lazy的影响
六、映射组成关系
———————————————————————————
<component …
<property …
七、多对多
———————————————————————————-
中间表的外键是联合主键
<set name=”当前set对象属性” table=”中间表” inverse=”true 由另一个对象维护”
<key column=”当前对象的外键” />
<many-to-many class=”中间表对应的另一个对象类型” column=”另一对象的外键”
* inverse=”true”
设置了inverse=”true”不能够主动解除关联关系,只能由另一方解除
* 级联删除,不一定成功,因为外键被其它引用了
在维护方配置cascade=”delete”
八、检索策略(Hibernate优化)
——————————————————————————–
Session.load();
* 立即检索
<class lazy=”false”
意即查询数据库
* 延迟检索
<class lazy=”true”
需要的时候才查询数据库,id、class除外;id在缓存中已经存在
* 代理对象
延迟检索会产生代理对象
特点:只初始化oid,其他的没有初始化
* 初始化代理对象
判断是否已经初始化Hibernate.isInitialized(Object)
初始化 Hibernate.initiaalize(Object) 会产生select语句
* 类级别检索
Session.get() 总是使用立即检索,不管lazy的值
Session.createQuery() 总是使用立即检索,不管lazy的值
九、关联级别检索策略
————————————————————————-
多对多/一对多
<set fetch=”join|select(默认)|subselect” lazy=”true(默认)|false|extra”
* get/load
* join-false join-true join-extra
迫切左外连接 迫切左外连接 迫切左外连接
* select-false select-true select-extra
立即检索 延迟检索 增强延迟检索
* subselect-false subselect-true subselect-extra
立即检索 延迟检索 增强延迟检索
* query
* join-false join-true join-extra
立即检索 延迟检索 增强延迟检索
* select-false select-true select-extra
立即检索 延迟检索 增强延迟检索
* subselect-false subselect-true subselect-extra –子查询extra除外
立即检索 延迟检索 增强延迟检索
多对一/一对一
<many-to-one fetch=”join|select(默认)” lazy=”false|proxy(默认)|no-proxy”
* get/load
* join-false join-proxy join-no-proxy
迫切左外连接 迫切左外连接 迫切左外连接
* select-false select-true select-extra
立即检索 延迟检索 增强延迟检索
* query
* join-false join-proxy join-no-proxy
立即检索 延迟检索 延迟检索
对端 代理看对端class的lazy值
批量检索
<set batch-size=”1 默认”
1的一端查询多的一端
表示都需要输出
如果是3就表示每三条合并成一条查询
<class name=”多的一端” batch-size=”1 默认”
多的一端查询1的一端
十、Hibernate检索方式
—————————————————————————–
- 导航对象图检索方式
- OID检索方式–主键
- HQL检索方式
- QBC检索方式
- API封装了基本串形式的语句
- 本地SQL检索方式
* HQL
1 |
Session.createQuery( "from Student" ); |
* QBC
1 |
Criteria c = Session.createCriteria(Student. class ); |
3 |
Criterion cn = Restrictions.eq( "name" , "tom" ); |
7 |
c.addOrder(Order.desc( "id" )); |
* 多态查询
1 |
Session.createQuery( "from java.io.Serializable c" ); |
查询所有实现Serializable接口的对象
* 分页
1 |
Query.setFirstResult( 3 ); |
2 |
Query.setMaxResults( 4 ); |
3 |
Criteria.setFirstResult( 3 ); |
4 |
Criteria.setMaxResults( 4 ); |
* 检索单个对象
1 |
Query.setMaxResults( 4 ); |
3 |
Criteria.setMaxResults( 4 ); |
4 |
Criteria.uniqueResult(); |
* 绑定参数
1 |
Session.createQuery( "from Student s where s.name = :name" ); |
2 |
Query.setString( "name" , "hello" ); |
4 |
Session.createQuery( "from Student s where s.name = ?" ); |
5 |
Query.setString( 0 , "hello" ); |
* 映射文件定义命名查询语句
1 |
< query name = "findStudent" > |
2 |
<![CDATA[FROM Student s]]> |
* 迫切左外连接
* 左外连接 left outer join
1 |
from Student s left outer join s.classes c |
* 投影查询 查询结果只是实体的一部分属性
* 投影查询 使用构造函数返回对象数组
* 报表查询
1 |
select count(*) from Student s |
2 |
Query.setMaxResults( 1 ); |
* 分组
1 |
select s.name,count(*) from Student s group by s.name |
3 |
Session.getNameQuery( "findStudent" ); |
十一、映射继承关系
——————————————————————————
一个表中带有标识符,父类子类使用同一样表
多张表,父类子类使用不同的表
<joined-subclass> 一个子类映射一张表
一个hbm配置文件
实体
entity-name=”"
默认不填是类名
一对一外键关联
<many-to-one name=”abc” unique=”true”
<one-to-one property-ref=”abc” />