3、Hibernate入门3

来源:互联网 发布:mr在lte网络优化 编辑:程序博客网 时间:2024/05/01 00:10

6、Hibernate的映射关系                                                                         

映射关系                            

XML(在<class/>配置)

Annoation

1 :1主键

参考类StuIdCard.hbm.xml 

<id name="id">

<generator class="foreign"></generator>

</id>

<one-to-one name="student" class="Student"

constrained="true"/>

主类(被参考表) Student.hbm.xml

<one-to-one name="stuIdCard" class="StuIdCard" property-ref=”student”/>

@OneToOne

@PrimaryKeyJoinColumn

双向: 实体类之间持有对方的引用

1 :1 外键

Employee.hbm.xml

<many-to-one name="person" class="Person" column="PERSON_ID"unique="true"/>

Person.hbm.xml

<one-to-one name="employee" class="Employee" property-ref="person"/>                                                                                  

@OneToOne

双向:@OneToOne(mappedBy=”在主要的类中定义”)

1 n  n : 1

多一方

设置外键

少一方写

Group.hbm.xml

<set name="users" cascade=”all” table=”” >  //与user做关联

       <key column="groupId"></key> //多的一方设置

       <one-to-many class="com.bjsxt.hibernate.User"/>

</set>

User.hbm.xml(双向)

<many-to-one name="group" class=”Group” column="groupId" />

单向

User

@ManyToOne

 

@OneToMany

@JoinColumn(name="groupId") //getUsers()前将在User表添加groupId外键字段,这样就会在多的一方设置

双向

Group

@OneToMany(mappedBy=”group”)

Public list getUser

n : m

Teacher.hbm.xml

<set name="students" table="t_s">   //持有对方的引用

       <key column="teacher_id"></key> //自己

<many-to-many class=" Student" column="student_id"/>

</set>

Student.hbm.xml

<set name="teachers" table="t_s">

       <key column="student_id"></key>

       <many-to-many class=" Teacher" column="teacher_id"/>

</set>

Teacher

@ManyToMany

@JoinTable(name="t_s",

       joinColumns={@JoinColumn(name="teacher_id")},

       inverseJoinColumns={@JoinColumn(name="student_id")}

)

双向:

Student

@ManyToMany(mappedBy="students")

组件映射

<component name=”wife” class=”Wife”>

 <property name=” wifeName” /> </component>

在主类getWife()上定义

@Embedded 被嵌入类不用写@Entity

联合主键

<compsite-id name=”对象”, class=”类”>

<key-property name=”key1” />

<key-property name=”key2”/>

</compsite-id>

在主类getWife()上定义

@OneToOne

@JoinColumns(

{@JoinColumn(name="wifeId",referencedColumnName="id"),

@JoinColumn(name="wifeName",referencedColumnName="name")

}

)

没有建外键关联是一件很危险的事,这时候会产生ID不一致的事,参考类ID要参考主类的ID

l   class (可选 -默认是通过反射得到的属性类型):被关联的类的名字。

l   constrained(约束) (可选)表明该类对应的数据库表,和被关联的对象所对应的数据库表之间,通过一个外键引用对主键进行约束。设置外键关联

l   property-ref: (可选)由对方那里设置

集合映射(在getUser()上设置)

@MapKey(name=”key”)for (Iterator <Map.Entry<Integer, User>> iter = g.getUser().entrySet().iterator(); iter.hasNext();) {Map.Entry<Integer, User> element = (Map.Entry<Integer, User>) iter.next();}for(Map.Entry<Integer, User> entry : g.getUser().entrySet()) {System.out.println(entry.getValue().getName());}@OrderBy(”user”)
关联更新

fetch 和 lazy 主要是用来级联查询的,   而 cascade 和 inverse 主要是用来级联插入和修改的             fetch参数指定了关联对象抓取的方式是select查询还是join查询,select方式时先查询返回要查询的主体对象(列表),再根据关联外键 id,每一个对象发一个select查询,获取关联的对象,形成n+1次查 询;而join方式,主体对象和关联对象用一句外键关联的sql同时查询出来,不会形成多次查询。
如果你的关联对象是延迟加载的,它当然不会去查询关联对象。另外,在hql查询中配置文件中设置的join方式是不起作用的(而在所有其他查询方式如get、criteria或再关联获取等等都是有效的),会使用 select方式,除非你在hql中指定join fetch某个关联对象。Fetch策略用于定义 get/load一个对象时,如何获取非lazy的对象/集合。这些参数在Query中无效。

当使用Hibernate中的one-to-many、many-to one、many-to-many关系映射的时候,一个对象中会包含一个或多个Set来关联其他的对象。例如:user-groups,当程序取user 对象时,如果一个用户有多个自定义组,那么程序将把组的信息也读取出来,在log中可以看到两个sql的输出。但是在页面的显示上,也许并不需要显示这个用户相关组的信息,这样系统的消耗就白白浪费了,于是hibernate提供了lazy(延迟加载)的方法来避免这一情况的发生,我们只需要在 user.hbm.xml中设置lazy=true(默认),就能实现延迟加载。

代码:

<set name="groupses" table="usergroups" catalog="many" cascade="save-update" lazy="true">               <key>                   <column name="userid" length="32" not-null="true" /> //自己              </key>               <many-to-many entity-name="com.example.model.Groups">                   <column name="groupid" length="32" not-null="true" />               </many-to-many>   </set>  

继承映射

每个类一张表(Andriod的hibernate_0300)

@Entity@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)public class Flight implements Serializable {}           

这种策略支持双向的一对多关联. 这里不支持IDENTITY生成器策略,因为id必须在多个表间共享.一旦使用这种策略就意味着你不能使用 AUTO 生成器和IDENTITY生成器. 这时候可以用@TableGenerator ID生成策略

<class name="com.bjsxt.hibernate.Animal" abstract="true"><id name="id"><generator class="assigned"/></id><property name="name"/><property name="sex"/><union-subclass name="com.bjsxt.hibernate.Pig" table="t_pig"><property name="weight"/></union-subclass><union-subclass name="com.bjsxt.hibernate.Bird" table="t_bird"><property name="height"/></union-subclass></class>

每个子类对应一张表,子类只写特有部分,但子类所对应的数据库表信息是完备的,即包含了所有从父类继承下来的属性映射的字段(这就是它跟joined-subclass的不同之处,joined-subclass定义的子类的表,只包含子类特有属性映射的字段)


父类跟子类一张表

整个继承层次结构中的父类和子类的所有属性都映射到同一个表中, 他们的实例通过一个辨别符(discriminator)列来区分.:

//父类@Entity@Inheritance(strategy=InheritanceType.SINGLE_TABLE)@DiscriminatorColumn(    name="planetype",    discriminatorType=DiscriminatorType.STRING)
//子类@Entity@DiscriminatorValue("A320")public class A320 extends Plane { ... }
<class name="Payment" table="PAYMENT">     <id name="id" type="long" column="PAYMENT_ID">         <generator class="native"/>     </id>     <discriminator column="PAYMENT_TYPE" type="string"/>     <property name="amount" column="AMOUNT"/>     ...      <subclass name="CreditCardPayment" discriminator-value="CREDIT">         <property name="creditCardType" column="CCTYPE"/>         ...      </subclass>     <subclass name="CashPayment" discriminator-value="CASH">         ...      </subclass>    …</class>

使用这种映射方式需要注意的是它通过<discriminator>标签(<discriminator column="employee_type"type="string"/>)增加一个字段(这里是employee_type字段)来标示某个记录是属于哪个实体对象的。通过<subclass>标记中的discriminator-value属性来定义哪个值代表哪个子类的持久化对象。.


链接的子类

当每个子类映射到一个表时, @PrimaryKeyJoinColumn@PrimaryKeyJoinColumns 注解定义了每个子类表关联到父类表的主键:

@Entity@Inheritance(strategy=InheritanceType.JOINED)public class Boat implements Serializable { ... }
@Entitypublic class Ferry extends Boat { ... }
@Entity@PrimaryKeyJoinColumn(name="BOAT_ID")public class AmericaCupClass  extends Boat { ... }

以上所有实体都使用了JOINED策略, Ferry表和Boat表使用同名的主键. 而AmericaCupClass表和Boat表使用了条件Boat.id = AmericaCupClass.BOAT_ID进行关联.主表包含共同的字段,子表就写特有的属性字段。此时子类的主键表参考主表的主键。

适用于不使用多态的情况下

·跟每个类建一张表的区别:

① 每个类一张表的映射策略所建立的表示独立的,每个表都包括子类所自定义 的属性和由父类锁继承的属性的映射字段。

② 只为具体类建表,子类所对应的表只包括子类所定义的属性,而子类所对应的 表与父类所对应的表是通过外键来进行关联的,即当持久化一个子类时,需要在父类的表和子类的表各增加一条记录,这两个记录通过外键来关联。

·好处:父类所定义的属性就在父类的表中进行映射,而子类所定义的属性就在子类的表中进行映射。避免了子类所定义的表中仍然需要定义父类属性的映射字段。

<class name="Employee" table="employee3">   <id name="oid" column="oid" >       <generator class="native">        </generator>   </id>   <property name="name" />     <joined-subclass name="HourlyEmployee" table="hourly2">    <key column="oid"></key>    <property name="rate"></property>    <many-to-one name="Company" column="companyid" cascade="save-update"></many-to-one>   </joined-subclass>   <joined-subclass name="SalariedEmployee" table="salaried2">    <key column="oid"></key>    <property name="salary"></property>    <many-to-one name="Company" column="companyid" cascade="save-update"></many-to-one>   </joined-subclass></class>

先表还是先类

实际工作当中先建表:对表进行优化,比如说建索引,建视图,建各种各样的优化

0 0
原创粉丝点击