Hibernate 映射值类型集合

假设Customer类中有orders属性和images属性,那么两者有相同的定义形式:

private Set orders = new HashSet();

private Set images = new HashSet();
orders属性与images属性的区别在于,前者存放的是实体类型的Order对象,而后者存放的是值类型的String对象。实体类型的对象有单独的OID和独立的生命周期,而值类型的对象没有单独的OID和独立的生命周期。

在映射文件中,用来映射值类型集合的元素有<set>、<idbag>、<list>和<map>。

1.映射Set

若Customer对象的images集合中不允许存放重复的照片名称,可以把images属性定义为Set类型,把IMAGES表的CUSTOMER_ID和FILENAME字段作为联合主键。

数据库表:

create table CUSTOMERS (
   ID bigint not null,
   NAME varchar(15),
   AGE int,
   primary key (ID)
);

create table IMAGES(
   CUSTOMER_ID bigint not null,
   FILENAME varchar(15) not null,
   primary key (CUSTOMER_ID,FILENAME),

   foreign key (CUSTOMER_ID) references CUSTOMERS(ID)

);

Customer.java:

public class Customer implements Serializable {
    private Long id;
    private String name;
    private int age;
    private Set images=new TreeSet();

    Constructor()...; getter()...; setter()...;

}

Customer.hbm.xml:

<hibernate-mapping >
  <class name="mypack.Customer" table="CUSTOMERS" >
    <id name="id" type="long" column="ID">
      <generator class="increment"/>
    </id>

    <property name="name" type="string" >
        <column name="NAME" length="15" />
    </property>

   <property name="age" type="int" >
        <column name="AGE" />
   </property>

   <set   name="images"   table="IMAGES"    lazy="true" >
        <key column="CUSTOMER_ID" />
        <element column="FILENAME" type="string"  not-null="true"/>
   </set>   

  </class>
</hibernate-mapping>

<element>子元素指定和images集合中元素相对应的字段是 FILENAME

lazy="true" 对images集合采用了延迟检索策略,当加载Customer对象时,需通过Hibernate的initialize()方法显式初始化images集合:

Hibernate.initialize(customer.getImages());

2.映射Bag

Bag集合中的对象不按特定方式排序,但允许有重复元素,Hibernate允许在持久化类中使用List来模拟Bag的行为。

若Customer对象的images集合中允许存放重复的照片文件名,可以把images属性定义为List类型,IMAGES表中需要定义一个代理主键ID。

数据库表为:

create table CUSTOMERS (
   ID bigint not null,
   NAME varchar(15),
   AGE int,
   primary key (ID)
);

create table IMAGES(
   ID bigint not null,
   CUSTOMER_ID bigint not null,
   FILENAME varchar(15) not null,
   primary key (ID),
   foreign key (CUSTOMER_ID) references CUSTOMERS(ID)
);

Customer.java:

public class Customer implements Serializable {
    private Long id;
    private String name;
    private int age;
    private List images=new ArrayList();

    Constructor()...; getter()...; setter()...;

}

Customer.hbm.xml:

<hibernate-mapping >
  <class name="mypack.Customer" table="CUSTOMERS" >
    <id name="id" type="long" column="ID">
      <generator class="increment"/>
    </id>

    <property name="name" type="string" >
        <column name="NAME" length="15" />
    </property>

   <property name="age" type="int" >
        <column name="AGE" />
   </property>

   <idbag   name="images"   table="IMAGES"    lazy="true">
        <collection-id type="long" column="ID">
           <generator class="increment"/>
        </collection-id>
        <key column="CUSTOMER_ID" />
        <element column="FILENAME" type="string"  not-null="true"/>
   </idbag>   

  </class>
</hibernate-mapping>

<collection-id>子元素用于设置IMAGES表的ID主键。

3.映射List

当用<idbag>映射images属性时,images集合中的元素不会按照索引位置排序。

若希望images集合中允许存放重复元素,并且按照索引位置排序,可在IAMGES表中定义一个POSITION字段,用以代表索引位置,然后用<list>映射。

数据库表:

create table CUSTOMERS (
   ID bigint not null,
   NAME varchar(15),
   AGE int,
   primary key (ID)
);

create table IMAGES(
   CUSTOMER_ID bigint not null,
   POSITION int not null,
   FILENAME varchar(15) not null,
   primary key (CUSTOMER_ID,POSITION),
   foreign key (CUSTOMER_ID) references CUSTOMERS(ID)
);

Customer.java:

public class Customer implements Serializable {
    private Long id;
    private String name;
    private int age;
    private List images=new ArrayList();

    Constructor()...; getter()...; setter()...;

}

Customer.hbm.xml:

<hibernate-mapping >
  <class name="mypack.Customer" table="CUSTOMERS" >
    <id name="id" type="long" column="ID">
      <generator class="increment"/>
    </id>

    <property name="name" type="string" >
        <column name="NAME" length="15" />
    </property>

   <property name="age" type="int" >
        <column name="AGE" />
   </property>

   <list   name="images"   table="IMAGES"    lazy="true">
        <key column="CUSTOMER_ID" />
        <list-index column="POSITION" />
        <element column="FILENAME" type="string"  not-null="true"/>
   </list>   

  </class>
</hibernate-mapping>

<list-index>子元素用于设置IMAGES表中代表索引位置的字段POSITION。

若将images属性定义为Java数组类型:

private String[] iamges;

由于Hibernate无法为数组创建代理,因此不能对数组类型的images集合使用延迟检索策略。

4.映射Map

若Customer类的images集合中的每一个元素包含一个键对象和值对象,那么应该把images集合定义为Map类型。在IMAGES表中定义一个IMAGE_NAME字段,和images集合中的键对象对应。

数据库表:

create table CUSTOMERS (
   ID bigint not null,
   NAME varchar(15),
   AGE int,
   primary key (ID)
);

create table IMAGES(
   CUSTOMER_ID bigint not null,
   IMAGE_NAME varchar(15) not null,
   FILENAME varchar(15) not null,
   primary key (CUSTOMER_ID,IMAGE_NAME),
   foreign key (CUSTOMER_ID) references CUSTOMERS(ID)
);

Customer.java:

public class Customer implements Serializable {
    private Long id;
    private String name;
    private int age;
    private Map images=new HashMap();

    Constructor()...; getter()...; setter()...;

}

Customer.hbm.xml:

<hibernate-mapping >
  <class name="mypack.Customer" table="CUSTOMERS" >
    <id name="id" type="long" column="ID">
      <generator class="increment"/>
    </id>

    <property name="name" type="string" >
        <column name="NAME" length="15" />
    </property>

   <property name="age" type="int" >
        <column name="AGE" />
   </property>

   <map   name="images"   table="IMAGES"    lazy="true">
        <key column="CUSTOMER_ID" />
        <map-key column="IMAGE_NAME" type="string"/>
        <element column="FILENAME" type="string"  not-null="true"/>
   </map>   

  </class>
</hibernate-mapping>

<map-key>子元素用于设置IMAGES表中和images集合的键对象对应的 IMAGE_NAME字段。

5.对集合排序

Hibernate对集合中的元素支持两种排序方式:数据库排序和内存排序。

映射文件中,Hibernate用sort属性来设置内存排序,用order-by属性来设置数据库排序。

排序属性<set><idbag><list><map>
sort(内存排序)支持不支持不支持支持
order-by(数据库排序)支持支持不支持支持

<set>、<idbag>和<map>均支持order-by属性

<set   name="images"   table="IMAGES"    lazy="true" order-by="FILENAME asc" >
     <key column="CUSTOMER_ID" />
     <element column="FILENAME" type="string"  not-null="true"/>
</set>   

order-by属性中可以加入SQL函数:

order-by="lower(FILENAME) desc"

<set>和<map>支持sort属性,可以设置自然排序或客户化排序。

<set   name="images"   table="IMAGES"    lazy="true" sort="natural" >  
     <key column="CUSTOMER_ID" />
     <element column="FILENAME" type="string"  not-null="true"/>
</set>  

<set   name="images"   table="IMAGES"    lazy="true" sort="mypack.ReverseStringComparator">  
     <key column="CUSTOMER_ID" />
     <element column="FILENAME" type="string"  not-null="true"/>
</set>  

ReverseStringComparator.java:

public class ReverseStringComparator implements Comparator{
  public int compare(Object o1,Object o2){
    String s1=(String)o1;
    String s2=(String)o2;

    if(s1.compareTo(s2)>0) return -1;
    if(s1.compareTo(s2)<0) return 1;

    return 0;
  }
}

6.映射组件类型集合

若照片包含照片名、文件名、长和宽等信息,可以专门定义一个Image组件类来表示照片。

Customer类和Image类之间是一对多的组成关系,Image类是值类型,没有OID。由于Image对象存放在Java集合中,为保证Java集合正常工作,应该在Image类中实现equals()和hashCode()方法。

数据库表:

create table CUSTOMERS (
   ID bigint not null,
   NAME varchar(15),
   AGE int,
   primary key (ID)
);

create table IMAGES(
  CUSTOMER_ID bigint not null,
  IMAGE_NAME varchar(15) not null,
  FILENAME varchar(15) not null,
  SIZEX int not null,
  SIZEY int not null,
  primary key (CUSTOMER_ID,IMAGE_NAME,FILENAME,SIZEX,SIZEY),
  foreign key (CUSTOMER_ID) references CUSTOMERS(ID)
);

Image.java:

public class Image implements Serializable {
    private String name;
    private String filename;
    private int sizeX;
    private int sizeY;
    private Customer customer;

    Constructor()...; getter()...; setter()...;

    public boolean equals(Object o){
      if(this==o) return true;
      if(! (o instanceof Image)) return false;
      final Image other=(Image)o;

      if(this.name.equals(other.getName())
        && this.filename.equals(other.getFilename())
        && this.sizeX==other.getSizeX()
        && this.sizeY==other.getSizeY())
        return true;
      else
        return false;
    }

   public int hashCode() {
     int result;
     result = name.hashCode();
     result = 29 * result + filename.hashCode()+sizeX+sizeY;
     return result;
   }
}

Customer.java:

public class Customer implements Serializable {
    private Long id;
    private String name;
    private int age;
    private Set images=new HashSet();

    Constructor()...; getter()...; setter()...;

}

Customer.hbm.xml:

<hibernate-mapping >
  <class name="mypack.Customer" table="CUSTOMERS" >
    <id name="id" type="long" column="ID">
      <generator class="increment"/>
    </id>

    <property name="name" type="string" >
        <column name="NAME" length="15" />
    </property>

   <property name="age" type="int" >
        <column name="AGE" />
   </property>

 <set   name="images"   table="IMAGES"    lazy="true"  order-by="IMAGE_NAME asc">
        <key column="CUSTOMER_ID" />
       <composite-element  class="mypack.Image">
         <parent name="customer" />
         <property name="name" column="IMAGE_NAME" not-null="true" />
         <property name="filename" column="FILENAME" not-null="true" />
         <property name="sizeX" column="SIZEX" not-null="true" />
         <property name="sizeY" column="SIZEY" not-null="true" />
       </composite-element>
 </set>   

  </class>
</hibernate-mapping><hibernate-mapping >
  <class name="mypack.Customer" table="CUSTOMERS" >
    <id name="id" type="long" column="ID">
      <generator class="increment"/>
    </id>

    <property name="name" type="string" >
        <column name="NAME" length="15" />
    </property>

   <property name="age" type="int" >
        <column name="AGE" />
   </property>

 <set   name="images"   table="IMAGES"    lazy="true"  order-by="IMAGE_NAME asc">
        <key column="CUSTOMER_ID" />
       <composite-element  class="mypack.Image">
         <parent name="customer" />
         <property name="name" column="IMAGE_NAME" not-null="true" />
         <property name="filename" column="FILENAME" not-null="true" />
         <property name="sizeX" column="SIZEX" not-null="true" />
         <property name="sizeY" column="SIZEY" not-null="true" />
       </composite-element>
 </set>   

  </class>
</hibernate-mapping>

<composite-element>子元素用于映射Image组件类, <parent>子元素用于映射Image类的customer属性, <property>子元素用于映射Image类的name、filename、sizeX和sizeY属性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值