Hibernate-01简介:Hibernate 开源O/R映射框架(ORM)
分层:下层为上层提供服务
表示层:struts webWork JSF
业务层:spring
持久层:与业务无关 hibernate(冬眠:让对象冬眠) ibatis
数据库:
OOA:面向对象的分析
OOD:面向对象的设计
OOP:面型对象的编程
阻抗不匹配(Java类中的继承关系不能体现在关系型数据库中)
创建的其他O/R映射框架:
ApacheOJB
JDO java数据对象
Toplink(oracle)
EJB(2.0cmp)(3.0 JPA)
IBatis(严格意义上讲不是OR框架,轻量级)
Hibernate优点:
1,无需SQL,效率更高(JDBC不需要我们写了)
2,使开发更面向对象化
3,移植性高
4,实现了透明持久化,不需要继承或实现Hibernate包中的任何类或接口(pojo)
5,没有侵入性(轻量级)
Hibernate缺点:
1,不支持批量操作
2,使用到数据库特用功能的时候就不能使用Hibernate(因为sql是自动生成的)
Hibernate-02例子
pojo.hbm.xml:映射文件
1,新建项目
2,创建User Library,加入jar包
*HIBERNATE_HOME/hibernate3.jar
*HIBERNATE_HOME/lib/*.jar
*数据库驱动jar
3,创建Hibernate配置文件:hibernate.cfg.xml(HIBERNATE_HOME/etc)
为了便于调试,将log4j.properties加入到项目中
4,创建一个实体类pojo
5,定义User类的映射文件POJO.hbm.xml
6,将POJO.hbm.xml引入到件ibernate.cfg.xml中
7,写一个类,将实体类生成数据库表
Configurationcfg = new Configuration().configure();
SchemaExport se = newSchemaExport(cfg);
se.create(true, true);
8,通过 Configuration cfg = newConfiguration().configure();
SessionFactorysf = cfg.buildSessionFactory();
Sessionsession = sf.openSession();
session.beginTransaction();
session.save(u);
session.getTransaction().commit();
session.close();
9,show_sql=true:显示hibernate执行的SQL语句
Hibernate-03核心接口
JNDI:同一管理对象资源,通过友好字符串可以获得一个对象(数据库连接池)
JDBC:事务管理只能针对同一个数据库
JTA:Java事务API,可以实现跨数据库事务的统一管理(跨行转账)
Hibernate-05_Session接口的基本用法及生命周期
1,了解Hibernate中的CRUD操作
save()
update()
saveOrUpdate()
get()
post()
2,了解get和load的区别:
get(),采用get方法加载数据库中的数据,如果不存在,返回null
load(),延迟加载,在执行load方法的时候不会发出sql语句,只是返回一个CGLIB代理对象,只有在真正第一次使用查询出对象的时候才发出SQL语句查询数据库;采用load方法加载数据库中的数据,如果不存在,则抛出异常
3,transient状态的特征:
*在数据库中没有与之匹配的数据
*没有加入session的管理
persistent状态的特征:
*在数据库中存在(不绝对)
*同时纳入了session管理
*在清理缓存(脏数据检查)的时候会和数据库同步
4,detached状态的特征:
*在数据库中有与之对应的记录
*没有纳入session的管理
Hibernate-04持久对象的生命周期
瞬态:新创建的对象,在数据库中没有与之对应的记录
持久态:存入数据库,接收session的管理
游离态:在数据库中有与之对应的记录,但是脱离了session的管理
Hibernate-06_Query接口
1,Query查询所有记录:
Query query = session.createQuery("fromUser");
2,Query的分页:
//设置从的几条开始查询
query.setFirstResult(3);
//设置查询多少条
query.setMaxResults(2);
Hibernate-07基本映射标签和属性
Hibernate的基本映射:
实体类---表
实体类中的属性---表字段
采用<class></class>标签将实体类映射成数据库表
name
table
lazy
采用<property/>标签将普通属性映射成表字段
name
column
length
type(指定数据库中该字段的类型:一般情况下不需要指定)
update true|false 该字段不会出现在update的Sql语句中
insert true|false
unique 唯一性
not-null 是否为空
采用<id></id>配置数据库主键
<generator class="native"/>设置主键的自动增长
class="native/uuid/identity/sequence"
native----Hibernate完成的数字自增1,2,3...
uuid----生成一个32位的字符串
identity----sqlserver的自增
sequence----oracle的自增(1,2,...)
assigned----手动分配主键
采用<composite-id></composite-id>设置联合主键
实体类的设计原则(POJO):
1,实现一个默认的无参的构造方法
2,提供一个标识属性
3,使用非final的类(影响预加载)
4,为持久化字段声明访问器(提供get和set方法)
防止已经存在的表在重新导出的时候被覆盖:
在hibernate.cfg.xml里面加上配置
<propertyname="hbm2ddl.auto">true</property>
Hibernate-11一对一唯一外键关联映射-单向
一个人只有一个身份证:Person---->IDCard
Person IDCard
----------- -----------
id:int id:int
name:String cardNo:String
idCard:IDCard
单向时指:站在Person这一段可以看到IDCard对象
外键关联:在一张表中添加一个外键,指向关联表的主键(在Person表中添加外键指向IDCard的主键)
IDCard.hbm.xml
-----------------------------------------------
<classname="com.softeem.IDCard">
<id name="id">
<generatorclass="native"/>
</id>
<property name="cardNo"/>
</class>
Person.hbm.xml
-----------------------------------------------
<classname="com.softeem.Person">
<id name="id">
<generatorclass="native"/>
</id>
<property name="name"/>
一对一就是多对一中的特例:给外键条件了一个唯一性约束
<many-to-one name="idCard"unique="true"/>
</class>
Hibernate-12一对一唯一外键关联映射-双向
一个人只有一个身份证:Person<---->IDCard
Person IDCard
----------- -----------
id:int id:int
name:String cardNo:String
idCard:IDCard person:Person
外键双向关联:在一张表中添加一个外键,指向关联表的主键(在Person表中添加外键指向IDCard的主键)
-----------------------IDCard.hbm.xml------------------------
<classname="com.softeem.IDCard">
<id name="id">
<generatorclass="native"/>
</id>
<property name="cardNo"/>
一对一关联映射默认的是通过主键加载指定的对象
添加了property-ref属性之后,就表示加载的时候就根据person对象的idCard加载,因为icard也是唯一的,所以实现了一对一的关联
<one-to-one name="person"property-ref="idCard"/>
</class>
---------------------Person.hbm.xml-------------------------
<classname="com.softeem.Person">
<id name="id">
<generatorclass="native"/>
</id>
<property name="name"/>
一对一就是多对一中的特例:给外键条件了一个唯一性约束
<many-to-one name="idCard"unique="true"/>
</class>
Hibernate-15多对多关联映射-单向
一个用户对用多个角色,多个用户也可能具有同一个角色:User---->Role
User Role
-------------- --------------
id:int id:int
name:String name:String
roles:Set
多对多关联映射通常要采用第三方表,用来存放两者之间的关系
tb_user tb_user_role tb_role
----------------- ------------------- --------------------
id | name userid |roleid id | name
----------------- ------------------- --------------------
1 | 张三 1 | 2 1 | 经理
2 | 李四 1 | 3 2 | 主管
3 | 王五 2 | 1 3 | 领班
User.hbm.xml
-----------------------------------------------------------------
<classclass="com.softeem.User">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<!--添加table="tb_user_role",指明要引用第三方表,并且hibernate会自动创建这张表-->
<set name="roles"table="tb_user_role" order-by="userid">
<!--key标签表示,使用user的主键作为第三方表的一个外键,字段名为userid-->
<key column="userid"/>
<!--声明set集合映射到Role类对应得表,并且将映射表的主键作为第三方表的一个字段,并且将引入的这两个字段作为“复合主键”-->
<many-to_manycalss="com.softeem.Role" column="roleid"/>
</set>
</class>
Role.hbm.xml
-----------------------------------------------------------------
<classclass="com.softeem.Role">
<id name="id">
<generatorclass="native"/>
</id>
<property name="name"/>
</class>
Hibernate-16多对多关联映射-双向
一个用户对用多个角色,一个Role也对用多个用户:User<---->Role
User Role
-------------- --------------
id:int id:int
name:String name:String
roles:Set users:Set
多对多关联映射通常要采用第三方表,用来存放两者之间的关系
tb_user tb_user_role tb_role
----------------- ------------------- --------------------
id | name userid | roleid id | name
----------------- ------------------- --------------------
1 | 张三 1 | 2 1 | 经理
2 | 李四 1 | 3 2 | 主管
3 | 王五 2 | 1 3 | 领班
User.hbm.xml
-----------------------------------------------------------------
<classclass="com.softeem.User">
<id name="id">
<generatorclass="native"/>
</id>
<property name="name"/>
<!--添加table="tb_user_role",指明要引用第三方表,并且hibernate会自动创建这张表-->
<set name="roles"table="tb_user_role">
<!--key标签表示,使用user的主键作为第三方表的一个外键,字段名为userid-->
<key column="userid"/>
<!--声明set集合映射到Role类对应得表,并且将映射表的主键作为第三方表的一个字段,并且将引入的这两个字段作为“复合主键”-->
<many-to-manycalss="com.softeem.Role" column="roleid"/>
</set>
</class>
Role.hbm.xml
-----------------------------------------------------------------
<classclass="com.softeem.Role">
<id name="id">
<generatorclass="native"/>
</id>
<property name="name"/>
<!--指定的第三方表要与User中指定的完全一致-->
<set column="users"table="tb_user_role">
<key column="roleid"/>
<many-to-manyclass="com.softeem.User" column="userid"/>
</set>
</class>
Hibernate-17延迟加载lazy
延迟加载(懒加载):查询出的对象在使用的时候才加载进来
可以用在class标签 property标签 set标签 one2one和many2one
<class>标签上,可以取值:true/false
<property>标签上,可以取值:true/false 使用类增强工具,修改字节码达到代理的目的
<set><list>标签上,可以取值:true/false/extra
one2one和many2one单端关联,可以取值:false/proxy/noproxy
lazy概念,只有真正使用该对象时才会创建;对于Hibernate而言,只有真正使用对象的时候才会发出sql语句
CGLib可以对普通类进行代理
JDK的代理只能代理实现了接口的类
Hibernate-08多对一关联映射
多个用户属于一个组:User----Group
User Group
----------- -----------
id:int id:int
name:String name:String
group:Group
关联映射的本质:
将关联关系映射到数据库, 所谓的关联关系是对象模型在内存中的一个或 多个引用
User.hbm.xml:
<class name=”com.softeem.User”>
<idname="id">
<generator class="native"/>
</id>
<propertyname="name"/>
<many-to-onename="group" column="groupid"casecade="save-update">
</class>
Group.hbm.xml
<class name=”com.softeem.Group”>
<idname="id">
<generator class="native"/>
</id>
<propertyname="name"/>
</class>
Hibernate-09一对一主键关联映射-单向
一个人只有一个身份证:Person---->IDCard
Person IDCard
----------- -----------
id:int id:int
name:String cardNo:String
idCard:IDCard
单向时指:站在Person这一段可以看到IDCard对象
双向是指:站在Person这一段可以看到IDCard对象同时站在IDCard对象一段页可以看到对用的Person对象
主键关联:让关联对象的id(主键)保持一致,不用加任何字段;就是让Person的主键和IDCard保持一致,而不是自动增长
IDCard.hbm.xml
-----------------------------------------------
<class name="com.softeem.IDCard">
<idname="id">
<generator class="native"/>
</id>
<propertyname="cardNo"/>
</class>
Person.hbm.xml
-----------------------------------------------
<class name="com.softeem.Person">
<idname="id">
<generator class="foreign"> :设置成外键关联
<param name="property">idCard</param>:关联icCard对应主键
</gennerator>
</id>
<propertyname="name"/>
<one-to-one name="idCard" constrained="true"/>
添加上外键约束:指示hibernate怎样加载他的关联对象(默认根据主键加载)
一对一主键关联映射中,默认了casecade属性
</class>
Hibernate-10一对一主键关联映射-双向
一个人和一个身份证只能唯一对应:Person<---->IDCard
Person IDCard
----------- -----------
id:int id:int
name:String cardNo:String
idCard:IDCard person:Person
双向是指:站在Person这一段可以看到IDCard对象同时站在IDCard对象一段页可以看到对用的Person对象
主键关联:让关联对象的id(主键)保持一致,不用加任何字段;就是让Person的主键和IDCard保持一致,而不是自动增长
IDCard.hbm.xml
-----------------------------------------------
<class name="com.softeem.IDCard">
<idname="id">
<generator class="native"/>
</id>
<propertyname="cardNo"/>
<one-to-one name="person"/>
默认抓取策略fetch=“jion”,只发一条外连接查询语句
</class>
Person.hbm.xml
-----------------------------------------------
<class name="com.softeem.Person">
<idname="id">
<generator class="foreign"> :设置成外键关联
<param name="property">idCard</param>:关联icCard对应主键
</gennerator>
</id>
<propertyname="name"/>
<one-to-one name="idCard" constrained="true"/>
添加上外键约束:指示hibernate怎样加载他的关联对象(默认根据主键加载)
一对一主键关联映射中,默认了casecade属性
</class>
Hibernate-13一对多关联映射-单向
一个班级对应多名学生:Classes---->Student
Classes Student
-------------------- ------------
id:int id:int
name:String name:String
students:Set<Student>
多对一关联映射:在一得一端加一个外键,指向多的一端,维护的关系是多指向一
一对多关联映射:在加载一个班级的时候能够加载班级中所有的学生,在多的一端加一个外键,指向一的一端,维护的关系是一指向多
--------------------------Classess.hbm.xml---------------------------
<class name="com.softeem.Classes">
<id name="id">
<generatorclass="native"/>
</id>
<propertyname="name"/>
<setname="students">
<!--这一句话的作用是在student表中添加一个主键,指向classes的id-->
<!--执行的时候student表中的classis字段为空,添加classes记录之后执行修改,所以这个字段不能添加非空约束,不然就不能保存-->
<keycolumn="classid"/>
<!--指定执行时的加载对象-->
<one-to-many class="com.softeem.Student"/>
</set>
</class>
--------------------------Student.hbm.xml--------------------------
<class class="com.softeem.Student">
<id name="id">
<generatorclass="native"/>
</id>
<propertyname="name"/>
</class>
Hibernate-14一对多关联映射-双向
一对多关联映射双向:Classes<---->Student
Classes Student
-------------------- ------------
id:int id:int
name:String name:String
students:Set<Student> classes:Classes
一对多双向关联映射:加载Classes的时候能够加载这个班级所有的学生信息,同时在加载一个Student的时候能够加载这个学生所在的班级信息
-------------------------Classess.hbm.xml----------------------------
<class name="com.softeem.Classes">
<id name="id">
<generatorclass="native"/>
</id>
<propertyname="name"/>
<!--invase反转属性:允许在多的一端维护关系(在学生的classid为null但是关系存在)-->
<!--相当于反转成了多对一关系:不会再发出update语句-->
<!--设置反转之后,先将Classes给student对象设置进去,student不用sava了,通过级联完成存储-->
<setname="students" inverse="true" casecade="all">
<keycolumn="classid"/><!--指定执行时的加载对象-->
<one-to-many class="com.softeem.Student"/>
</set>
</class>
------------------------Student.hbm.xml-----------------------------
<class class="com.softeem.Student">
<id name="id">
<generatorclass="native"/>
</id>
<propertyname="name"/>
<!--映射的时候需要注意,这个字段的名字要和一的一端指定的字段名字相同-->
<!--多对一存储的时候:需要先存储多的一端的对象-->
<!--一对多存储的时候:需要先存储多的一端的对象-->
<many-to-one name="classes" column="classid"/>
</class>
Hibernate-18继承映射
继承映射的三种策略:
1,(单表继承)每棵类继承树映射成一张表
2,(具体表继承)每个子类映射成一张表
3,(类表继承)每个具体类映射成一张表
1,每棵继承树映射成一张表(就是将父类和子类中所有的属性都映射成一张表的字段)
Id | Name | Sex | Weight | Height | type |
对于每一个子类,在生成的表中添加一个字段来区别他们
Animal Pig(继承Animal) Bird(继承Animal)
--------------------- ------------------ -----------------------
id weight height
name
sex
extends.hbm.xml
<classname=”com.softeem.Animal” table=”t_animal”>
<id name=”id”>
<generatorclass=”native”/>
</id>
<!—加入鉴别器:用来区别子类的类型,对应于type字段-->
<discriminator column=”type”type=”string”/>
<property name=”name”/>
<property name=”sex”/>
</class>
<sub- classname=”Pig”extends=”Animal” discriminator-value=”p”>
<property name=”weight”/>
</sub-class>
<sub- class name=”Bird”extends=”Animal” discriminator-value=”b”>
<property name=”height”/>
</sub-class>
<hibernate-mappingpackage=”com.softeem”>
<classname=” Animal” table=”t_animal”>
<id name=”id”>
<generatorclass=”native”/>
</id>
<!—加入鉴别器:用来区别子类的类型,对应于type字段-->
<discriminator column=”type”type=”string”/>
<property name=”name”/>
<property name=”sex”/>
<sub- class name=”Pig” discriminator-value=”p”>
<propertyname=”weight”/>
</sub-class>
<sub- class name=”Bird” discriminator-value=”b”>
<propertyname=”height”/>
</sub-class>
</class>
</hibernate-mapping>
2,(具体表继承)每个子类映射成一张表
t_animal
Id | Name | sex |
1 | 小猪 | 男 |
2 | 小鸟 | 女 |
t_pig
Pid(animal_id) | weight |
1 | 30kg |
t_bird
Bid(animal_id) | height |
2 | 12m |
<hibernate-mappingpackage=”com.softeem”>
<class name=”Animal”table=”t_animal”>
<idname=”id”>
<generatorclass=”native”/>
</id>
<propertyname=”name”/>
<propertyname=”sex”/>
<joined-subclass name=”Pig”table=”t_pig”>
<keycolumn=”pid”/>
<propertyname=”weight”/>
</joined-subclass>
<joined-subclass name=”Bird”table=”t_bird”>
<keycolumn=”bid”/>
<propertyname=”height”/>
</joined-subclass>
</class>
</hibernate-mapping>
3(类表继承)每个具体类映射成一张表
t_pig
Id | Name | Sex | weight |
t_bird
Id | Name | Sex | height |
<hibernate-mappingpackage=”com.softeem”>
<class name=”Animal”table=”t_animal”>
<idname=”id”>
<generatorclass=”uuid”/>
</id>
<propertyname=”name”/>
<propertyname=”sex”/>
<union-subclass name=”Pig” table=”t_pig”>
<propertyname=”weight”/>
</joined-subclass>
< union -subclass name=”Bird”table=”t_bird”>
<propertyname=”height”/>
</joined-subclass>
</class>
</hibernate-mapping>