Hibernate(二)

今天讲了一些关于hibenate的映射关系,有一对多,多对一,一对一,多对多
等等,学完这节课,我还真想自己整理笔记的,整理到一半突然发现,汤老师的笔记整理的是那么的完美。
我希望看到我博客的人,能够吸收到更多充实的知识。虽然本人博客写了2个月了,毕竟还是菜鸟一个,不过呢,
在传智的2个月内已经学到了许多以前不曾知道的知识。下面我先是将汤老师的笔记复制了过来。以下还有代码,
我就说说作为我一个初学者,在学习中犯下的错误吧。我相信看到的人一定会有所收获的。

* 集合映射
如果实体类有一个集合类型的属性,就需要一张额外的表,即所谓的集合表,这
个表有一个外键引用实体类对应的表的主键。

根据集合中存放的元素类型可以分为两种:1,值类型集合,元素是可识别的数据
库类型,如基本数据类型或字符串类型等;2,实体类型集合,元素是其他的实体。

** 对集合做映射时一般需要指定:
1)集合表的表名,在相应元素中使用属性table指定;
2)集合外键,是在子元素key中用属性column属性指定一个列名,他是一个外键
   引用了实体表的主键;
3)集合元素,对于值类型集合,使用元素element指定;对于实体类型集合,使
   用元素one-to-many或many-to-many。
4)如果是索引集合,如List,数组或Map(bag不是),还需要指定一个集合表中
   的索引字段,用于对应到数组索引或List的索引,或者Map的key。
   a) 如果是List或数组,需要指定(集合表中的)一个用于保存索引的列,用
      元素list-index指定。
   b) 如果是Map:key用map-key元素指定;如果key是一个实体引用,则是通过
      map-key-many-to-many来配置。

JAVA的实体类中集合只能定义成接口不能定义成具体类,因为在运行时集合会被
替换成Hibernate的实现。

在实体类中声明集合时,可进行初始化。比如Set addresses = new HashSet();
这样做的目的是方便往集合中添加元素,调用getAddresses().add(element)就可
以了,不需再做是否为null的判断。  注意,我们只在把addresses初始化为一个
HashSet的实例,在运行时,集合会被Hibernate替换为自已的实现。

用于映射集合类的元素是由集合接口的类型决定的:
  <set>  元素用来映射 java.util.Set  类型的属性;
  <list> 元素用来映射 java.util.List 类型的属性;
  <array>元素用来映射对象类型的数组;
  <primitive-array>元素用来映射原始数据类型的数组;
  <bag>  元素用来映射 java.util.List 类型的属性(允许重复但没有顺序);
  <map>  元素用来映射 java.util.Map  类型的属性;

1,Set,一个用户(User)有多个地址,地址是字符串类型的。
    <set name="addresses" table="itcast_useraddresses">
     <key column="userId"></key>
     <element type="string" column="address"></element>
    </set>

2,List,与Set相比,需要在表中增加一列用于保存索引(元素在List中保存的
   顺序,不对应实体的任何属性)。用<list-index>元素指定:
    <list name="phoneNumbers" table="itcast_user_phonenumbers">
     <key column="userId"></key>
     <list-index column="idx"></list-index>
     <element type="string" column="phoneNumber"></element>
    </list>

3,a) 对象类型数组,跟配置list类似,只不过把list-index元素替换为index元
   素,作用一样:
    <array name="addresses2" table="itcast_user_addresses2">
     <key column="userId"></key>
     <index column="idx"></index>
     <element type="string" column="address"></element>
    </array>
 
   b) 原始类型数组,把array元素名替换为array:
    <primitive-array name="phoneNumbers2" table="user_phonenumbers2">
     <key column="userId"></key>
     <index column="idx"></index>
     <element type="integer" column="phoneNumber"></element>
    </primitive-array>

4,bag,可以有重复元素,但不保存顺序。实体中声明为java.util.List类型
   (不用指定list-index,因为bag不保存顺序):
    <bag name="addresses3" table="itcast_user_addresses3">
     <key column="userId"></key>
     <element type="string" column="address"></element>
    </bag>

5,Map,需要映射key的value:
    <map name="phoneNumbers3" table="itcast_user_phonenumbers3">
     <key column="userId"></key>
     <map-key type="string" column="idx"></map-key>
     <element type="string" column="phoneNumber"></element>
    </map>


* 有序集合
有两种方式实现:
  a) 使用sort属性实现在内存中排序;
  b) 使用order-by属性实现 在使用sql进行查询时使用order by指定顺序。

有序集合对于List或数组无效,因为列表元素的顺序由列表索引指明。

如果使用的是Set或Map类型的集合,并且在实体中对这个集合属性进行了初始化,
应是SortedSet或SortedMap实现类的实例(TreeSet或TreeMap)。

** sort属性
可以用于set或map映射,默认为unsorted,即不排序;可以设为natural,要求实
体要实现java.lang.Comparable接口。分类集合的行为象TreeSet或者TreeMap,
这是从数据库中取出记录后再在内存中进行排序。(在查询时有效)

** order-by属性
在set、bag或map映射中使用order-by属性,指定查询时生成的sql的order by子
句,这是在执行sql查询时指定排序(推荐)。如果使用了order-by,则返回的就
是可以保存顺序的集合实现类。

* 一对多与多对一映射:User与Group
在User.hbm.xml中增加:
    <many-to-one name="group" column="groupId"></many-to-one>
在Group.hbm.xml中增加:
    <set name="users">
        <key column="groupId"></key>
        <one-to-many class="User"/>
    </set> 

这是做的双向关联,即从任何一方都可以得到另一方(User.getGroup得到所属的
组或Group.getUsers得到组中所有的用户);双方也都可以维护关系,维护关系
是指更新外键这一列的的值; 如果只有一方进行映射,就是单向关联。 如果去
掉了User.hbm.xml中的many-to-one映射,只有Group.hbm.xml中有一个set的映射,
这就是单向一对多关联,这时只能由Group维护关系,并且只能从Group得到User。
同样,如果只去掉Group.hbm.xml中的set映射,就是单向多对一关联。

树形结构,就是自己和自己是一个一对多的关系。如Group有父组和子组,映射文件
中为:
    <many-to-one name="parent" column="parentId"/>
    <set name="children">
        <key column="parentId"/>
        <!-- 集合中的元素还是Group -->
        <one-to-many class="Group"/>
    </set>

* 一对一映射:User与IdCard
有两种映射方式:基于主键和一对一和基于外键和一对一(用数据库说明)。不
管哪种方式,都是有外键的那个表对应的实体(IdCard)来维护关系;只为只有
IdCard能维护关系,所以如果要做单向关联,只能做从IdCard到User的单向关联。

不管是多对一还是一对一,有外键的那个表所对应的实体始终能够维护关系。

** 基于主键的一对一
在IdCard.hbm.xml中把主键生成策略改为foreign,并设置one-to-one:
    ...
    <generator class="foreign">
        <param name="property">user</param>
    </generator>
 ...
    one-to-one name="user" constrained="true"></one-to-one>
 
    属性constrained="true"表示该类对应的表的的主键同时作为外键引用User
    表的主键,默认为false。

在User.hbm.xml中增加:
    <one-to-one name="idCard"></one-to-one>

** 基于外键的一对一
在IdCard.hbm.xml中增加:
    <many-to-one name="user" column="userId" unique="true"/>
   
    其中属性unique="true"说明这一列的值是唯一的,不能重复。基于外键的一
    对一其实就是多对一的一个特例。

在User.hbm.xml中增加:
    <one-to-one name="idCard" property-ref="user"></one-to-one>

    !!其中property-ref属性用来指定关联类的一个属性,这个属性将会和外
    键相对应,如果没有指定,会使用对方关联类的主键(所以上面的基于主键
    的一对一时不用指定)。


* 多对多映射:Group与Role
在Group.hbm.xml中增加:
    <set name="roles" table="itcast_groups_roles">
        <key column="groupId"></key>
        <many-to-many class="Role" column="roleId"></many-to-many>
    </set>
在Role.hbm.xml中增加:
    <set name="groups" table="itcast_groups_roles">
        <key column="roleId"></key>
        <many-to-many class="Group" column="groupId"></many-to-many>
    </set>

双方一定要在set元素中指定相同的表名(这是指定的中间表的名字)。元素
many-to-many 的class 属性用于指定关联类(集合中的实体元素)的名称;因为
是多对多,关联类在中间表中也是用一个外键指定的,many-to-many中的column
属性用于指定这个外键的列名。

这是做的双向关联,此时双方都可以维护关系。去掉任何一方的映射,就是单向
的双对多关联。

* 属性:lazy
延迟加载,默认值为true,即集合的属性值默认是不加载的。强制加载可以通过
在session环境中使用这个集合属性或者使用:Hibernate.initialize(proxy);
当相关联的session关闭后,再访问懒加载的对象将出现异常。

这些都是一些实体类:有Group,User,IdCard,Role
package cn.itcast.demo.entities;

import java.util.HashSet;
import java.util.Set;

public class Group {

 private int id;
 private String name;

 private Set<User> users = new HashSet<User>();

 private Group parent;
 private Set<Group> children;

 private Set<Role> roles = new HashSet<Role>();

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public Set<User> getUsers() {
  return users;
 }

 public void setUsers(Set<User> users) {
  this.users = users;
 }

 public Group getParent() {
  return parent;
 }

 public void setParent(Group parent) {
  this.parent = parent;
 }

 public Set<Group> getChildren() {
  return children;
 }

 public void setChildren(Set<Group> children) {
  this.children = children;
 }

 public Set<Role> getRoles() {
  return roles;
 }

 public void setRoles(Set<Role> roles) {
  this.roles = roles;
 }

}
package cn.itcast.demo.entities;

public class IdCard {

 private int id;
 private String sn;

 private User user;

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getSn() {
  return sn;
 }

 public void setSn(String sn) {
  this.sn = sn;
 }

 public User getUser() {
  return user;
 }

 public void setUser(User user) {
  this.user = user;
 }

}
package cn.itcast.demo.entities;

import java.util.HashSet;
import java.util.Set;

public class Role {

 private int id;
 private String name;

 private Set<Group> groups = new HashSet<Group>();

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public Set<Group> getGroups() {
  return groups;
 }

 public void setGroups(Set<Group> groups) {
  this.groups = groups;
 }

}
package cn.itcast.demo.entities;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

public class User implements java.lang.Comparable<User> {

 private int id;
 private String name;
 private String desc;

 private Date birthday;
 private byte[] avatar;

 private Set<String> addresses = new TreeSet<String>();
 private String[] addresses2;
 private List<String> addresses3 = new ArrayList<String>();

 private List<String> phoneNumbers = new ArrayList<String>();
 private int[] phoneNumbers2;

 private Map<String, String> phoneNumbers3 = new HashMap<String, String>();

 private Group group;
 private IdCard idCard;

 public User() {
 }

 public User(int id) {
  this.id = id;
 }

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getDesc() {
  return desc;
 }

 public List<String> getAddresses3() {
  return addresses3;
 }

 public void setAddresses3(List<String> addresses3) {
  this.addresses3 = addresses3;
 }

 public void setDesc(String desc) {
  this.desc = desc;
 }

 public Date getBirthday() {
  return birthday;
 }

 public void setBirthday(Date birthday) {
  this.birthday = birthday;
 }

 public byte[] getAvatar() {
  return avatar;
 }

 public void setAvatar(byte[] avatar) {
  this.avatar = avatar;
 }

 public Set<String> getAddresses() {
  return addresses;
 }

 public Map<String, String> getPhoneNumbers3() {
  return phoneNumbers3;
 }

 public void setPhoneNumbers3(Map<String, String> phoneNumbers3) {
  this.phoneNumbers3 = phoneNumbers3;
 }

 public void setAddresses(Set<String> addresses) {
  this.addresses = addresses;
 }

 public List<String> getPhoneNumbers() {
  return phoneNumbers;
 }

 public void setPhoneNumbers(List<String> phoneNumbers) {
  this.phoneNumbers = phoneNumbers;
 }

 public String[] getAddresses2() {
  return addresses2;
 }

 public IdCard getIdCard() {
  return idCard;
 }

 public void setIdCard(IdCard idCard) {
  this.idCard = idCard;
 }

 public void setAddresses2(String[] addresses2) {
  this.addresses2 = addresses2;
 }

 public int[] getPhoneNumbers2() {
  return phoneNumbers2;
 }

 public void setPhoneNumbers2(int[] phoneNumbers2) {
  this.phoneNumbers2 = phoneNumbers2;
 }

 public int compareTo(User o) {
  return this.id - o.id;
 }

 public Group getGroup() {
  return group;
 }

 public void setGroup(Group group) {
  this.group = group;
 }

 @Override
 public String toString() {
  return new StringBuffer()//
    .append("[User: id=").append(id) //
    .append(",name=").append(name)//
    .append("]")//
    .toString();
 }

 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + id;
  return result;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  final User other = (User) obj;
  if (id != other.id)
   return false;
  return true;
 }

}


这些都是一些实体类Group,User,IdCard,Role所对应的表。                                                                                                                                
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.demo.entities">
 <class name="Group" table="itcast_group">
  <id name="id" >
   <generator class="native" />
  </id>
  <property name="name" type="string"/>
  
  <!--
  -->
  <set name="users" >
   <key column="groupId"></key>
   <one-to-many class="User"/>
  </set>
  
  <many-to-one name="parent" column="parentId"/>
  <set name="children">
   <key column="parentId"/>
   <one-to-many class="Group"/>
  </set>
  
  <set name="roles" table="itcast_groups_roles" lazy="true">
   <key column="groupId"></key>
   <many-to-many class="Role" column="roleId"></many-to-many>
  </set>

 </class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.demo.entities">
 <class name="IdCard" table="itcast_idcard">
  <id name="id">
   <generator class="native"></generator>
  </id>
  <property name="sn" type="string" />
  <many-to-one name="user" column="userId" unique="true"></many-to-one>

  <!--  基于主键的一对一映射
   <id name="id">
   <generator class="foreign">
   <param name="property">user</param>
   </generator>
   </id>
   <one-to-one name="user" constrained="true"></one-to-one>
  -->
 </class>
</hibernate-mapping>

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.demo.entities">
 <class name="Role" table="itcast_role">
  <id name="id">
   <generator class="native" />
  </id>
  <property name="name" type="string" />

  <set name="groups" table="itcast_groups_roles">
   <key column="roleId"></key>
   <many-to-many class="Group" column="groupId"></many-to-many>
  </set>

 </class>
</hibernate-mapping>


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.demo.entities">
 <class name="User" table="itcast_user">
  <id name="id" unsaved-value="undefined">
   <generator class="native" />
  </id>
  <property name="name" type="string" />
  <property name="birthday" type="date" />
  <property name="desc" column="desc_" type="text" />

  <property name="avatar" length="512000" type="binary" />
  <!--
   <property name="avatar" >
   <column name="avatar" sql-type="MEDIUMBLOB"/>
   </property>
  -->

  <!--
   <set name="addresses" table="itcast_user_addresses" order-by="address desc">
  -->
  <set  name="addresses" table="itcast_user_addresses" sort="natural">
   <key column="userId"></key>
   <element type="string" column="address"></element>
  </set>

  <array name="addresses2" table="itcast_user_addresses2"  >
   <key column="userId"></key>
   <list-index column="idx"></list-index>
   <element type="string" column="address"></element>
  </array>

  <list name="phoneNumbers" table="itcast_user_phoneNumbers">
   <key column="userId"></key>
   <list-index column="idx"></list-index>
   <element type="string" column="phoneNumber"></element>
  </list>

  <primitive-array name="phoneNumbers2" table="itcast_phoneNumbers2">
   <key column="userId"></key>
   <list-index column="idx"></list-index>
   <element type="integer" column="phoneNumber"></element>
  </primitive-array>

  <bag name="addresses3" table="itcast_user_addresses3">
   <key column="userId"></key>
   <element type="string" column="address"></element>
  </bag>

  <map name="phoneNumbers3" table="itcast_user_phoneNumbers3">
   <key column="userId"></key>
   <map-key type="string" column="`key`"></map-key>
   <element type="string" column="phoneNumber"></element>
  </map>

  <!--
  -->
  <many-to-one name="group" column="groupId" ></many-to-one>
  
  <!-- 基于主键的一对一映射
  <one-to-one name="idCard"></one-to-one>
   -->
  
  <one-to-one name="idCard" property-ref="user"></one-to-one>
  
 </class>
</hibernate-mapping>



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值