【Hibernate】3.hibernate映射
来源:互联网 发布:淘宝在哪里买装修模板 编辑:程序博客网 时间:2024/06/05 20:29
Hibernate O/R映射(实体映射)
实体映射作为类与表之间的联系纽带。
1.实体映射基础(Hibernate中类/表映射、属性/字段映射的基本技术)
类表映射主要包括:
a)表名——类名映射:<class name="" table="">...</class>
b)主键映射:<id name="" column="" type=""><generator class=""/></id>
①.id标签,标识符,自动增加,一般不会对其操作(包括删除、修改等)。
name="id" 声明了Java属性的名字 - Hibernate会使用getId()和setId()来访问它。 column属性则告诉Hibernate, 我们使用EVENTS表的哪 个字段作为主键。
嵌套标签generator说明id生成策略。一般为native。
②.generator元素用来设定标识符生成器,hibernate提供了多种内置的实现。
increment 由Hibernate自动以递增的方式生成标识符,每次增量为1. identity 由底层数据库生成标识符,前提是底层数据库支持自动增长字段类型。 sequence hibernate根据底层数据库的序列生成标识符,前提是底层数据库支持序列。 hilo native 根据底层数据库对自动生成标识符的支持能力,选择identity、sequence或hilo。 uuid.hex hibernate采用128位的UUID算法来生成标识符。 assigned 由java应用程序来生成标识符。
c)字段映射:<property name="" type="" column=""/>
①.是除id外声明其他属性所需标签,对于一些非保留关键字属性可以直接映射成为相同名称的字段。type有时可省略,此时Hibernate会试着去确定转换类型和映射类型,但可能出现转换错误。
数据库提供的主键生成机制,一般是通过一个内部表保存当前主键状态(如对自增型主键,保存的是当前的最大值和递增量),操作时,先读取最大值,然后加上递增量,作为新的主键,更新到内部表中。
2.高级映射技术(自定义数据类型、复合主键,特殊字段的相关映射技术)
a)自定义数据类型(????)
b)复合主键(???)
c)Blob、Clob字段的映射:(???)
3.实体映射策略??
4.延迟加载
对于Query接口的list()方法与iterator()方法来说,都可以实现查询,但是list()返回的每个对象都是完整的(对象中的每个属性都被表中的字段填充了),而iterator()方法返回的对象中仅仅包含了主键值,只有当对iterator()中的对象进行操作时,Hibernate才会向数据库再次发送查询语句获取该对象的属性值,所有list()方法的效率更高。所有iterator()这种形式叫做延迟加载。
5.1.立即检索策略: 即lazy=''false"
在一对多关联级别中一般使用延迟检索
默认立即检索策略的缺点
1).select语句的的数目太多,需要频繁的访问数据库,会影响检索性能。
如需查询n个所需对象,则需执行n+1次select查询语句。这种检索策略没有利用SQL的连接查询。在一对多中,若无需访问关联对象,则加载关联对象会耗费内存。
5.2.延迟检索策略: 即lazy=''true"
优点:由应用程序决定需要加载那些对象,可避免执行多余的select语句,以及避免加载应用程序不需要访问的对象,提高了检索性能,并节省了内存空间。
缺点:应用程序若想访问游离状态的代理类实例,必须保证在持久化状态时已被初始化。
适用范围:
一对多或者多对多关联
5.3左外连接检索策略
默认情况下,多对一关联级别使用左外连接检索策略
优点:a.对应用程序完全透明,不管对象处于持久化还是游离状态,应用程序都可以方便的从一个对象导航到与他关联的对象。
b.使用了外连接,select语句数目少。
缺点:a.可能回加载应用程序不需访问的对象,浪费内存;
b.复杂的数据库表也会影响检索性能。
适用范围:
a.多对一或者一对一关联。
b.应用程序需立即访问的对象;
c.数据库系统具有良好的表连接性能。
6.数据关联
6.1一对一关联<one-to-one>
(1)主键关联:两张关联表通过主键形成一对一映射关系。cascade 级联,默认使用了左外连接的策略(即fetch=“join”,fetch=“select”表示使用立即检索,即默认是立即加载,两条单独的select语句,若要修改为延迟加载,则需为<one-to-one>标签添加属性constrained=“”,在主控方添加lazy=“true”)(待加载一方)。
主控方: <class name="A" table="t_a"> <id name="" column="" type=""> <generator class="native"/> </id> <property name=""/> <one-to-one name="b" class="B" cascade="all"/> </class>
被控方: <class name="B" table="t_b"> <id name="" column="" type=""> <generator class="foreign"> <param name="property">a</param> </generator> foreign主键生成
</id> <property name=""/> <one-to-one name="a" class="A" constrained="true"/>constrained约束 </class>
由于采用了主键关联方式,则通过主键关联的两张表,其关联记录的主键值须保持同步。
(2)唯一外键关联:由<many-to-one>节点定义,唯一外键关联的一对一关系只是多对一关系的一个特例。
//主控方: <class name="A" table="t_a"> <id name="" column="" type=""> <generator class="native"/> </id> <property name=""/> <many-to-one name="b" class="B" column="" unique="true"/> </class>
//被控方:<class name="B" table="t_b"> <id name="" column="" type=""><generator class="native"> <param name="property">a</param></generator> </id> <property name=""/> <one-to-one name="a" class="A" property-ref="b"/></class>
当只有主控方的时候是单向关系,当被控方中也有一个属性是主控方类型的,则形成了双向关联。
6.2一对多关联
(1)单向一对多关系:只需在“一”方进行配置。
主控方: <class name="A" table="t_a" dynamic-update=“true” dynamic-insert=“true”> dynamic级联更新 <id name="" column="" type=""> <generator class="native"/> </id> <property name=""/> <set name="b" table="t_b" cascade="all' order-by=""> <key column=""/> <one-to-many class="B"/> </set> </class>
由于是单向关联,为了保持关联关系,只能通过主控方对被控方进行级联更新。
但更新时会存在id空问题。
(2)双向一对多关系:需要在关联双方均加以配置。
Hibernate中的延迟加载,当我们在程序中获取到了“一”的一方,但是不需要多的一方,则可以使用延迟加载。
是“一对多”与“多对一”关联的组合,在主控方配置单向一对多关系的基础上,在被控方配置与其对应的多对一关系。
主控方: <class name="A" table="t_a" dynamic-update=“true” dynamic-insert=“true”> <id name="" column="" type=""> <generator class="native"/> </id> <property name=""/> <set name="b" table="t_b" inverse="true" inverse控制方向反转 cascade="all' lazy="false" order-by=""> <key column=""/> <one-to-many class="B"/> </set> </class>
被控方:<class name="B" table="t_b" dynamic-update=“false” dynamic-insert=“false> <id name="" column="" type=""> <generator class="native"> <param name="property">a</param> </generator> </id> <property name=""/> <many-to-one name="a" class="A" update="true" insert="true" cascade="none".../></class>
主控方的inverse被设为“true”,将不是主控方,将关联关系的维护工作交给了管理对象B来完成。即关联关系中inverse=“false”的为主控方。
6.3多对多关联
需要借助中间表完成多对多映射信息的保存。应避免使用,根据情况采取延迟加载来避免无谓的性能开销。
<class name="com.xx.xxx.Student" table="tb_student"> <id name="id" column="id" type="string"> <generator class="uuid"/> </id> <property name="name" column="name" type="string"/> <set name"courses" table="student_course" cascade="save-update"> <key column="student_id"/> <many-to-many class="com.xx.xxx.Course" column="course_id"/> </set></class>注意:其中set标签中table表示中间表自动生成,cascade表示级联,key标签表示中间表中与当前表关联的列,<many-to-many> 中class表示当前表与另一个表的多对多关系,column表示中间表中与另一个表关联的列
6.4.Map 映射
6.4.1.Map键值对——值为简单类型变量
<class name="com.xx.xxx.Team" table="team"> <id name="id" column="id" type="string"> <generator class="uuid"/> </id> <property name="name" column="name" type="string"/> <map name"students" table="student"> <key column="team_id"/><index column="name" type="string">key值</index>//指定的是map中的key值<element column="description" type="string">value值</element>//指定的是map中的value值</map></class>
6.4.2.Map键值对——值为对象类型变量
<class name="com.xx.xxx.Team" table="team"> <id name="id" column="id" type="string"> <generator class="uuid"/> </id> <property name="name" column="name" type="string"/> <map name"students" table="student" cascade="all"> <key column="team_id"/><index column="card_id" type="string">key值</index> <one-to-many class="com.xx.xxx.Student" /> </map></class>
<class name="com.xx.xxx.Student" table="student"> <id name="id" column="id" type="string"> <generator class="uuid"/> </id> <property name="name" column="name" type="string"/><property name="age" column="age" type="int"/><property name="cardId" column="card_id" type="string"/><many-to-one name="team" column="team_id" class="com.xx.xxx.Team"/></class>
6.5.Set 映射
<class name="com.xx.xxx.Team" table="team"> <id name="id" column="id" type="string"> <generator class="uuid"/> </id> <property name="name" column="name" type="string"/> <set name"students" table="student"> <key column="team_id"/> <element column="name" type="string" /> </set></class>Map与Set标签中的elecment子标签映射的是原子类型,即能够直接映射到数据库表字段上的类型,而one-to-many映射的是实体类型。
6.6.List映射
<class name="com.xx.xxx.Team" table="team"><id name="id" column="id" type="string">
<generator class="uuid"/>
</id>
<property name="name" column="name" type="string"/>
<list name"students" table="student" cascade="all">
<key column="team_id"/>
<index column="index" ></index>
<ont-to-many calss="com.xx.xxx.Student" />
</list>
</class>其中<index>标签指定list中的顺序,<list>标签中“一”的一方不能添加invalse=“true”,因为在<index>标签有序,不能将维护交给关联方。
6.7.Bag映射
结合了List和Set,可以重复且没有顺序的一种集合,是由Hibernate提供的。
Hibernate使用LIst来模拟Bag,相对于List,少了<index>标签
<class name="com.xx.xxx.Team" table="team"> <id name="id" column="id" type="string"> <generator class="uuid"/> </id> <property name="name" column="name" type="string"/> <bag name"students" table="student" cascade="all" inverse="true"> <key column="team_id"/> <ont-to-many calss="com.xx.xxx.Student" /> </bag></class>
6.8.联合主键映射规则
两种实现方式分别为:将联合主键与其他属性放在同一类中;或者是将联合主键提取放在单独类中
1).实体类:类中的每个主键属性都对应数据表中的主键列,Hibernate要求具有联合主键的实体类实现Serializable接口,并重写hashCode()方法和equals()方法,重写这两个方法的原因在于Hibernate要根据数据库的联合主键来判断某两行记录是否是一样的,若一样,则为同一个对象,若不同,则为两个对象,这反映到程序中就是根据haseCode与equals方法来判断某两个对象是否能够放到诸如Set这样的集合中。实现Serializable接口的原因在于使用get或load方法的时候需要先构建出来该实体的对象,并且将查询依据(联合主键)设置进去,然后作为get或load方法的第二个参数传递进去即可。
2).映射文件:
1).实体类:类中的每个主键属性都对应数据表中的主键列,Hibernate要求具有联合主键的实体类实现Serializable接口,并重写hashCode()方法和equals()方法,重写这两个方法的原因在于Hibernate要根据数据库的联合主键来判断某两行记录是否是一样的,若一样,则为同一个对象,若不同,则为两个对象,这反映到程序中就是根据haseCode与equals方法来判断某两个对象是否能够放到诸如Set这样的集合中。实现Serializable接口的原因在于使用get或load方法的时候需要先构建出来该实体的对象,并且将查询依据(联合主键)设置进去,然后作为get或load方法的第二个参数传递进去即可。
2).映射文件:
<class name="com.xx.xxx.Student" table="tb_student"> <composite-id> <key-property name="cardId" column="card_id" type="string" /> <key-property name="name" column="name" type="string" /> </composite-id> <property name="age" column="age" type="int"/></class>
<class name="com.xx.xxx.Student" table="tb_student"> <composite-id name="studentPrimaryKey" class="com.xx.xxx.studentPrimaryKey"> <key-property name="cardId" column="card_id" type="string" /> <key-property name="name" column="name" type="string" /> </composite-id> <property name="age" column="age" type="int"/></class>
6.9.组件映射
在一个类中包含另一个类
<class name="com.xx.xxx.Student" table="tb_student"> <id name="id" column="id" type="string"> <generator class="uuid"/> </id> <property name="name" column="name" type="string"/> <component name"address" class="com.xx.xxx.Adress"> <property name="homeAddress" type="string"/> <property name="schoolAddress" type="string"/> </component></class>
6.10.继承映射
1).每个子类一张表:每个子类一个hbm文件,父类没有hbm映射信息。即父类没有对应的表,父类中的字段相应的加在了每个子类中。
2).一张表存储继承体系中的所有类的信息:即将继承体系中的所有字段放在一张表中。
需要在hbm文件中增加<discriminator column="" type=""></discriminator >,区分子类等信息。
<class name="com.xx.xxx.Person" table="person"> <id name="id" column="id" type="string"> <generator class="uuid"/> </id> <discriminator column="personType" type="String"/> <property name="name" column="name" type="string"/> <subclass name"com.xx.xxx.Student" discriminator-value="student"> <property name="cardId" type="string"/> </subclass> <subclass name"com.xx.xxx.Teacher" discriminator-value="teacher"> <property name="salary" type="int"/> </subclass></class>
3).公共信息放在父类表中,独有信息放在了子类表中,每个子类对应一张表。查询等操作需涉及两张表。
<class name="com.xx.xxx.Person" table="person"> <id name="id" column="id" type="string"> <generator class="uuid"/> </id> <property name="name" type="string"/> <joined-subclass name"com.xx.xxx.Student" discriminator-value="student"> <key column="id"/> <property name="cardId" type="string"/> </joined-subclass> <joined-subclass name"com.xx.xxx.Teacher" discriminator-value="teacher"> <key column="id"/> <property name="salary" type="int"/> </joined-subclass></class>
6.10.关联映射
要考虑到关联方向(directionality),阶数(multiplicity)和集合(collection)的行为
6.10.1.单向Set-based的关联
用Java的集合类(collection):Set,因为set 不包含重复的元素及与我们无关的排序。
对于多对多关联(或叫n:m实体关系), 需要一个关联表(association table)。
值类型的集合
6.10.2.双向关联
首先把集合加入到相应的实体类中。然后再映射文件中修改配置;
所有的双向关联需要有一端被设置为inverse。在一对多关联中它必须是代表多(many)的那端。而在多对多(many-to-many)关联中,你可以任意选取一端,因为两端之间并没有差别。
6.10.1.单向Set-based的关联
用Java的集合类(collection):Set,因为set 不包含重复的元素及与我们无关的排序。
对于多对多关联(或叫n:m实体关系), 需要一个关联表(association table)。
<set name="events" table="person_event"> <key column="person_id"/> <many-to-many column="event_id" class="events.Event"/></set>其中name是该类中的一个属性,对应于一个关联表,表名是由set元素的table属性配置的。前者用<key>,后者用<many-to-many>元素的column属性定义。同时告知其所在的类。
值类型的集合
<set name="emailAddresses" table="person_email_addr"> <key column="person_id"/> <element column="email_addr" type="string"/></set>比较这次和此前映射的差别,主要在于element部分,这次并没有包含对其它实体引用的集合,而是元素类型为String的集合(在映射中使用小写的名字”string“是向你表明它是一个Hibernate的映射类型或者类型转换器)。和之前一样,set元素的table属性决定了用于集合的表名。key元素定义了在集合表中外键的字段名。element元素的column属性定义用于实际保存String值的字段名。
6.10.2.双向关联
首先把集合加入到相应的实体类中。然后再映射文件中修改配置;
<set name="participants" table="person_event" inverse="true"> <key column="person_id"/> <many-to-many column="person_id" class="events.Person"/></set>与单向关联的区别是射文件里增加了set元素的inverse="true"属性
所有的双向关联需要有一端被设置为inverse。在一对多关联中它必须是代表多(many)的那端。而在多对多(many-to-many)关联中,你可以任意选取一端,因为两端之间并没有差别。
</class>
6.7.Bag映射
阅读全文
0 0
- 【Hibernate】3.hibernate映射
- hibernate映射
- hibernate映射
- hibernate映射
- hibernate映射
- Hibernate 映射
- hibernate映射
- hibernate映射
- Hibernate------映射
- Hibernate映射
- hibernate映射
- hibernate 映射
- hibernate映射
- Hibernate映射
- hibernate映射
- Hibernate映射
- hibernate映射
- hibernate映射
- linux各个配置
- BP神经网络-异或问题
- Linux 网络编程
- handlerbars转义和反转义
- QT控件大全 十 QPower
- 【Hibernate】3.hibernate映射
- Ubuntu 16.04下Qt交叉编译开发环境搭建
- SQLite 常用函数
- redis关闭保护模式
- JQuery以JSON方式提交数据到服务端
- android.permission.MOUNT_UNMOUNT_FILESYSTEMS权限
- 21.AlertDialog普通对话框的使用
- '$.browser.msie' 为空或不是对象的问题
- ADC多通道逐次转换(不用DMA)