您的位置:首页 > 其它

Hibernate学习(一)--Hibernate知识要点3

2011-03-14 19:19 239 查看
Query接口

关系映射
这里的关系映射指的是对象之间的关系,并不是指数据库的关系. 关系映射解决的问题是,当对象处于各种关系时,数据库表该如何映射,编程时如何处理.
一对一:单向(主键,外键),双向(主键,外键)
一对多:单向,双向(和多对一双向相同)
多对一:单向,双向(一对多双向和多对一双向是一样的)
多对多:单向,双向
(一对一单/双向主键关联映射,只作了解)
集合映射:list ,map,set
继承映射(了解):单表,多表,一张主表多张子表
组件映射:@Embeddable,@Embedded

一对一(one to one) 单向关联映射
两个对象是一对一的的关系.
有两种策略可以实现一对一的关联映射
l 主键关联:即让两个对象具有相同的主键值,以表明他们之间的一对一的对应关系;数据库表不会有额外的字段来维护他们之间的关系,仅通过表的主键关系来维护.一对一主键关联映射默认了级联属性,其关联对象会同时存储.所以不会抛出TransientObjectException异常.
l 唯一外键关联:外键关联,本来是用于多对一的配置,但是如果加上唯一的限制之后,也可以表示一对一的关联关系. unique="true".
单向关联,如Person-person_id;加载person信息时能关联对应的person_id信息
双向关系,加载任何一方,都能关联出别一方的信息.
注意id的主键生成策略,foreign使用另外一个相关联的对象的标识符。通常和<one-to-one>联合起来使用。
类Person(id,name,idCard),
类IdCard(id,cardNo)

一对一(单向)基于主键关联映射(了解)
XML配置方法
一对一单向主键关联通常使用一个特定的id生成器。
<class name="Person" table=”t_person”>
<id name="id" >
<generator class="foreign">
<param name="property">idCard</param>
</generator>
</id>
<one-to-one name="idCard" constrained="true"/>
</class>
one-to-one不会加载字段,它告诉HIBERNATE怎样加载其引用对象.如何加载呢,默认根据主键加载其引用对象.如在t_person中查到id=2,自动加载t_idCard中id=2的对象信息. constrained="true",表明person主键是个外键,表示当前主键上存在着idCard约束,当前主键id作为外键,参照了idCard.
<param name="property">idCard</param>表明person中的id来源于idCard,也就是共享idCard的主键.
Annotation配置一对一(单向)主键关联映射.(BUG)
@OneToOne
@PrimaryKeyJoinColumn
有BUG,系统不会生成主键映射.推荐使用XML配置方法.

一对一(单向)基于外键关联映射
和单向多对一关联几乎是一样的。唯一不同的就是单向一对一关联中的外键字段具有唯一性约束。这种方法会在表中生成一个新的外键字段.如果不限制外字段的唯一性约束,就会导致产生多对一的关联. 指定多的一端unique="true",这样就限制了多的一端的多重性为一.
<class name="Person" table=”t_person”>
<id name="id" >
<generator class="native"/>
</id>
<property name=”name”/>
<many-to-one name="idCard" column="addressId" unique="true"

not-null="true"/>
</class>
这种状态注意TransientObjectException异常.在保存时就先保存外键idCard,再保存Person类.
一对一单向外键关联Annotation配置
@OneToOne
@JoinColumn(name="指定生成的外键字段名字")

一对一(双向)主键关联映射(了解)
PersonßàIdCard.在另一端也加上一个一对一的单向关联映射.
模型对象
Person(id,name,idCard)
IdCard(id,cardNo,person)中,双方都持有对方的属性引用.
一对一(双向)主键关联映射XML配置方式
在IdCard配置中建立映射,<one-to-one name="person"/>指示Hibernate如何加载,默认情况下根据主键加载.也就是在基于单向一对一的映射中, 在另一端也加上一个单向一对一的主键关联映射.
在Person一端配置
<class name="Person" table=”t_person”>
<id name="id" >
<generator class="foreign">
<param name="property">idCard</param>
</generator>
</id>
<one-to-one name="idCard" constrained="true"/>
</class>
在另一端IdCard配置
<class name=" IdCard " table=”t_idCard”>
<id name="id" >
<generator class="native"/>
</id>
<property name=”cardNo”/>
<one-to-one name="person" property-ref=”idCard” />
</class>
一对一(双向)主键关联映射Annotation(BUG)
在两端各自的引用属性上加上
@OneToOne
@PrimaryKeyJoinColumn

一对一(双向)唯一外键关联映射
Personß----àIdCard.在另一端也加上一个一对一的单向关联映射.
在模型对象
Person(id,name,idCard)
IdCard(id,cardNo,person),
双方都持有对方的属性引用.
需要在另一端加上<one-to-one>,指示hibernate如何加载,默认情况下根据主键加载person;因为外键关联映射中,两个实体的关系是由person的外键idCard来维护的,所以不能指定person的主键来加载person,而应根据person的外键idCard来加载person对象.
一对一双向外键关联映射XML配置方式
Person一端:用多对一配置外键唯一形成一对一的配置方式.
<class name="Person" table=”t_person”>
<id name="id" >
<generator class="native"/>
</id>
<property name=”name”/>
<many-to-one name="idCard" column="addressId" unique="true"/>

</class>
IdCard一端:一对一,引用另一端外键
<class name=" IdCard " table=”t_idCard”>
<id name="id" >
<generator class="native"/>
</id>
<property name=”cardNo”/>
<one-to-one name="person" property-ref="idCard"/>
</class>
要想加载idCard,如果不加property-ref,默认根据person主键id来加载,property- ref="idCard"就指示hibernate从person里面的idCard属性来加载.
一对一双向外键关联映射Annotation配置方式
双方互持对方的属性的引用
关系模型
Husband(id,name,wife)
Wife(id,name,husband)
在Husband一端的wife属性上注解
@OneToOne
//@JoinColumn
在Wife一端的husband加上注解,mappedBy
@OneToOne(mappedBy="wife")引用属性
加上mappedBy属性后就可以在wife这一端告知这个关联是在wife属性上设置的.就不用管理wife这一端生成的husband的设置.生成的wife表格不会有husband字段.
规律:有双向关联时mappedBy通常必设.

联合主键一对一单向外键关联映射
对象模型
Wife(id,name,age) WifePk(id,name)
Husband(id,name,wife)
1 在Wife中建立联合主键生成策略
@IdClass(WifePk.Class)
@Id
2 在Husband中添加个外键即可
@OneToOne
3自定义Husband中外键的名字
@OneToOne
@JoinColumns(
{
@JoinColumn(name="wifeId", referencedColumnName="id"),
@JoinColumn(name="wifeName", referencedColumnName="name")
}
)
XML配置方式:略

组件映射
对象关系:一个对象是另一个对象的一部分
数据库表:是一张表
Annotation:@Embeddable,@Embedded
XML:<component>
对象模型
Husband(id,name,wife)
Wife(wifeName,wifeAge)
Annotation:
在Husband的wife属性上建立注解
@Embedded 表明该对象是从别的位置嵌入过来的,是不需要单独映射的表.
这种方式生成的表为husband(id,name,wifename,wifeage),不会生成wife表.
@AttributeOverride注解可以覆盖该属性对应的嵌入式对象的列映射:
XML:
<class name="Husband" >
<id name="id">
<generator class="native"/>
</id>
<property name="name"></property>
<component name="wife">
<property name="wifeName"/>
<property name="wifeAge"/>
</component>
</class>

多对一(many to one)单向关联映射
多对一的数据库设计原则:在多的那下端加外键
//注意在创建实体类属性时应尽量避免与SQL语句中的关键字重名.
多对一单向关联映射
实体模型(User多对一Group)
User(id,name,group)多
Group(id,groupname)一

Annotation配置
@Entity
@Table(name="t_group")//注意表名与SQL中关键字重名
只需要在多的一端User属性group进行注解配置
@ManyToOne
@JoinColumn(name=”groupId”)
XML配置
<many-to-one name="group" column="groupId" />
标签会在”多”的一端添加外键,相当于在数据库中添加外键
生成的表为user(id,name,groupid),t_group(id,groupname)
属性cascade
<many-to-one name="group" column="groupid" cascade="all"/>
取值all,none,save-update,delete,对象间的级联操作,只对增删改起作用.
在存储时User时,设置了cascade="all"会自动存储相应的t_group.而不用管user关联的对象(通常情况下会优先存储关联的对象,然后再存储user).

一对多(one to many)单向关联映射
模型(group一对多user)
Group(id,name,users)一
User(id,name)多
设计时在一的这一端存在着多的集合,生成的数据库表通常是在多的一端生成外键.
Set<User> users=new HashSet<User>()
一对多单向外键关联映射
在一的这一端Group端users属性上进行注解配置
@OneToMany
@JoinColumn(name="groupId")
如果不指定生成的外键列@JoinColumn(name="groupId"),默认会生成多对多的关系,产生一张中间表.
XML配置中配置一的那一端Group
<class name="com.hibernate.Group" table="t_group">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="users">
<key column="groupId"/>指定生成外键字段的名字
<one-to-many class="com.hibernate.User"/>
</set>
</class>

规律:
l 单向时, 一方存在另一方的引用,数据库表中体现为外键.配置时一般只用配置一端.
l 双向时,双方互持对方的引用,要进行双向两端的配置.基于annotation的双向配置中,在一端配置好后,在另一端必须用指定mappedby属性.
l 关于一对多/多对一数据库设计时,总是在多的一端加外键.通常在多的一端指定生成的外键名称.

一对多/多对一双向关联
一对多与多对一的双向关联是同一种情况.
关系模型(group一对多user)
Group(id,name,users)一
User(id,name,group)多
Set<User> users=new HashSet<User>()
配置规则:一般以多的一端为主,先配置多的一端
在多的一端User端配置group
@ManyToOne
在一的一端Group端配置时,在users只需要加个mappedBy="group"
@OneToMany(mappedBy="group")
XML配置
Group中
<set name="users">
<key column="groupId"/>
<one-to-many class="com.hibernate.User"/>
</set>
在User中
<many-to-one name="group" column="groupId"/>
务必确保在多的一端生成的生成的外键和一的一方生成的外键的名字相同,都为groupId.
如果名字不同则会在多的一端生成多余的外键.
create table t_group (
id integer not null auto_increment,
name varchar(255),
primary key (id)
)
create table t_user (
id integer not null auto_increment,
name varchar(255),
groupId integer,
primary key (id)
)
alter table t_user
add index FKCB63CCB6C3D18669 (groupId),
add constraint FKCB63CCB6C3D18669
foreign key (groupId) references t_group (id)

多对多单向关联
关系举例:老师à学生,老师需要知道自己教了哪些学生,但学生不知道自己被哪些老师来教.
数据库:中间表
Annotation:@ManyToMany
XML:<many-to-many>
关系模型(Teache多对多Student),从Teacher这一端能关联到students.
Teacher(id,name,students)多
Student(id,name)多
Set<Student> students=new HashSet<Student>()
在Teacher那一端配置
@ManyToMany
如果手动指定生成的中间表的表名和字段名
@JoinTable(
name="t_s", //表名
joinColumns={@JoinColumn(name="teacher_id")},//指向teacher表
inverseJoinColumns={@JoinColumn(name="student_id")}//指向另一张表
)
生成的表为
create table Student (
id integer not null auto_increment,
name varchar(255),
primary key (id)
)
create table Teacher (
id integer not null auto_increment,
name varchar(255),
primary key (id)
)
create table t_s (//生成的中间表
teacher_id integer not null,
student_id integer not null,
primary key (teacher_id, student_id)
)
t_s表的两个属性分别references其它表的主键.
XML中
<class name="com.xxx.Teacher">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="students" table="t_s">table定义中间表的表名
<key column="teacher_id"></key>
<many-to-many class="com.xxx.Student" column="student_id"/>
</set>
</class>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: