zoukankan      html  css  js  c++  java
  • Hibernate的映射组件属性

    组件属性

    如果持久化类的属性并不是基本数据类型,也不是一个日期或者字符串常量,而是一个复合类型的对象,例如 private Name name; 那么这就是一个组件属性。

    组件属性可以是任何普通的java类对象,在映射文件中则用<compent>标签标识,<compent>中又可以像<class>那样包含<property>子元素,此外<compent>中还可以包含一个<parent>子元素用来指向容器实体。

    下面演示组件属性的用法,比如在Person持久化类中有一个Name属性,

     1 package com;
     2 
     3 
     4 public class Person {
     5     public Integer getId() {
     6         return id;
     7     }
     8     public void setId(Integer id) {
     9         this.id = id;
    10     }
    11     public int getAge() {
    12         return age;
    13     }
    14     public void setAge(int age) {
    15         this.age = age;
    16     }
    17     public Name getName() {
    18         return name;
    19     }
    20     public void setName(Name name) {
    21         this.name = name;
    22     }
    23     private Integer id;
    24     private int age;
    25     private Name name;
    26     
    27 }

    name属性的类型Name只是一个普通的java类,

     1 package com;
     2 
     3 
     4 public class Name {
     5     public String getFirst() {
     6         return first;
     7     }
     8     public void setFirst(String first) {
     9         this.first = first;
    10     }
    11     public String getLast() {
    12         return last;
    13     }
    14     public void setLast(String last) {
    15         this.last = last;
    16     }
    17     public Person getOwner() {
    18         return owner;
    19     }
    20     public void setOwner(Person owner) {
    21         this.owner = owner;
    22     }
    23     private String first;
    24     private String last;
    25     private Person owner;
    26     public Name() {
    27         
    28     }
    29     public Name(String first, String last) {
    30         this.first = first;
    31         this.last = last;
    32     }
    33 }

    那么在person类的映射文件中,需要用<compent>表明name为一个组件属性,

     1 <?xml version="1.0"  encoding="UTF-8"?>    
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
     4 
     5 <hibernate-mapping package="com">
     6     <class name="Person" table="Person_inf">
     7         <id name="id" column="person_id" type="int">
     8             <generator class="identity" />
     9         </id>
    10         <property name="age" type="int" />
    11         <component name="name" class="Name" unique="true">
    12             <parent name="owner"/>
    13             <property name="first" />
    14             <property name="last" />
    15         </component>
    16     </class>
    17 </hibernate-mapping>

    下面写一个测试类,

     1 package com;
     2 
     3 import java.util.HashMap;
     4 import java.util.Map;
     5 
     6 import org.hibernate.Session;
     7 import org.hibernate.SessionFactory;
     8 import org.hibernate.Transaction;
     9 import org.hibernate.cfg.Configuration;
    10 
    11 public class PersonManager {
    12     public static void exec(String resource, Object obj) {
    13         // 打开线程安全的session
    14         Configuration conf = new Configuration().configure();
    15         conf.addResource("com/"+resource);
    16         // 用Configuration创建SessionFactory
    17         SessionFactory sf = conf.buildSessionFactory();
    18         // 用SessionFactory打开Session
    19         Session sess = sf.openSession();
    20         Transaction tx = sess.beginTransaction();
    21         sess.save(obj);
    22         tx.commit();
    23         sess.close();
    24         sf.close();
    25     }
    26     
    27     public static void ComponentTest() {
    28         Person cp = new Person();
    29         cp.setAge(30);
    30         Name name = new Name("天王盖地虎","宝塔镇河妖");
    31         cp.setName(name);
    32         exec("Person.hbm.xml",cp);
    33     }
    34     
    35     public static void main(String[] args) {
    36         ComponentTest();
    37     }
    38 }

    执行程序,会发现hibernate生成的person_inf表中,hibernate将组件属性name映射成了person_inf表中的两个列

    组件属性为集合

    如果组件属性是一个集合,例如list, map, set等, 那么可以在<compent>中包含<list> <set> <map>等子元素。

    还是以上面的person为例,假如person的name属性中,多了一个power属性,power是map类型,

     1 package com;
     2 
     3 
     4 public class MapPerson {
     5     public Integer getId() {
     6         return id;
     7     }
     8     public void setId(Integer id) {
     9         this.id = id;
    10     }
    11     public int getAge() {
    12         return age;
    13     }
    14     public void setAge(int age) {
    15         this.age = age;
    16     }
    17     public MapName getName() {
    18         return name;
    19     }
    20     public void setName(MapName name) {
    21         this.name = name;
    22     }
    23     private Integer id;
    24     private int age;
    25     private MapName name;
    26     
    27 }
     1 package com;
     2 
     3 import java.util.HashMap;
     4 import java.util.Map;
     5 
     6 public class MapName {
     7     public String getFirst() {
     8         return first;
     9     }
    10     public void setFirst(String first) {
    11         this.first = first;
    12     }
    13     public String getLast() {
    14         return last;
    15     }
    16     public void setLast(String last) {
    17         this.last = last;
    18     }
    19     public Person getOwner() {
    20         return owner;
    21     }
    22     public void setOwner(Person owner) {
    23         this.owner = owner;
    24     }
    25     public MapName() {
    26         
    27     }
    28     public MapName(String first, String last) {
    29         this.first = first;
    30         this.last = last;
    31     }
    32     
    33     public Map<String, Integer> getPower() {
    34         return power;
    35     }
    36     public void setPower(Map<String, Integer> power) {
    37         this.power = power;
    38     }
    39 
    40     private String first;
    41     private String last;
    42     private Person owner;
    43     private Map<String, Integer> power = new HashMap<String, Integer>();
    44 
    45 }

    因此在person类的映射文件中,需要在<compent>标签里增加<map>子标签,

     1 <?xml version="1.0"  encoding="UTF-8"?>    
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
     4 
     5 <hibernate-mapping package="com">
     6     <class name="MapPerson" table="Person_inf">
     7         <id name="id" column="person_id" type="int">
     8             <generator class="identity" />
     9         </id>
    10         <property name="age" type="int" />
    11         <component name="name" class="MapName" unique="true">
    12             <parent name="owner"/>
    13             <property name="first" />
    14             <property name="last" />
    15             <map name="power" table="name_power">
    16                 <key column="person_name_id" not-null="true" />
    17                 <map-key column="name_aspect" type="string" />
    18                 <element column="name_power" type="int"/>
    19             </map>
    20         </component>
    21     </class>
    22 </hibernate-mapping>

    在测试类中新增测试方法mapTest()

     1 public static void mapTest() {
     2     MapPerson mp = new MapPerson();
     3     mp.setAge(30);
     4     MapName mn = new MapName("天王盖地虎","宝塔镇河妖");
     5     Map<String, Integer> power = new HashMap<String, Integer>();
     6     power.put("力量", 100);
     7     power.put("速度", 90);
     8     mn.setPower(power);
     9     mp.setName(mn);
    10     exec("MapPerson.hbm.xml",mp);
    11 }

    执行测试类,发现在mysql中,持久化类的属性为集合元素的时候,hibernate会将它映射成单独的一个表,并用外键关联持久化类。 其实这已经在映射文件中配置了

    person_inf表

    name_power表

    集合属性的元素为组件

    这个跟前面的 “组件属性为集合”刚好反过来, 持久化类中的属性本身就是集合属性,在映射文件中依然用<list> <set> <map>等标签映射这些属性,不过对于这些属性中的值(集合元素),则用<composite-element>而不是<element>来映射。

    还是以person类为例,假如person类中有个属性nicks,是map类型,

     1 package com;
     2 
     3 import java.util.HashMap;
     4 import java.util.Map;
     5 
     6 public class MapComPerson {
     7     private Integer id;
     8     public Integer getId() {
     9         return id;
    10     }
    11     public void setId(Integer id) {
    12         this.id = id;
    13     }
    14     public int getAge() {
    15         return age;
    16     }
    17     public void setAge(int age) {
    18         this.age = age;
    19     }
    20     public Map<String, MapName> getNicks() {
    21         return nicks;
    22     }
    23     public void setNicks(Map<String, MapName> nicks) {
    24         this.nicks = nicks;
    25     }
    26     private int age;
    27     private Map<String, MapName> nicks = new HashMap<String, MapName>();
    28 }

    此时的Name类已经不再是person的属性,而是构成person属性nicks中的map元素值类型,

     1 package com;
     2 
     3 import java.util.HashMap;
     4 import java.util.Map;
     5 
     6 public class MapName {
     7     public String getFirst() {
     8         return first;
     9     }
    10     public void setFirst(String first) {
    11         this.first = first;
    12     }
    13     public String getLast() {
    14         return last;
    15     }
    16     public void setLast(String last) {
    17         this.last = last;
    18     }
    19     public Person getOwner() {
    20         return owner;
    21     }
    22     public void setOwner(Person owner) {
    23         this.owner = owner;
    24     }
    25     public MapName() {
    26         
    27     }
    28     public MapName(String first, String last) {
    29         this.first = first;
    30         this.last = last;
    31     }
    32     
    33     public Map<String, Integer> getPower() {
    34         return power;
    35     }
    36     public void setPower(Map<String, Integer> power) {
    37         this.power = power;
    38     }
    39 
    40     private String first;
    41     private String last;
    42     private Person owner;
    43     private Map<String, Integer> power = new HashMap<String, Integer>();
    44 
    45 }

    person类对应的映射文件,

     1 <?xml version="1.0"  encoding="UTF-8"?>    
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
     4 
     5 <hibernate-mapping package="com">
     6     <class name="MapComPerson" table="Person_inf">
     7         <id name="id" column="person_id" type="int">
     8             <generator class="identity" />
     9         </id>
    10         <property name="age" type="int" />
    11         <map name="nicks" table="nick_inf">
    12             <key column="person_id" not-null="true" />
    13             <map-key column="phase" type="string" />
    14             <composite-element class="MapName">
    15                 <parent name="owner" />
    16                 <property name="first" />
    17                 <property name="last" />
    18             </composite-element>
    19         </map>
    20     </class>
    21 </hibernate-mapping>

    在测试类中新增mapComponentTest()方法,

    public static void mapComponentTest() {
        MapComPerson mcp = new MapComPerson();
        mcp.setAge(25);
        
        Map<String, MapName> nick = new HashMap<String, MapName>();
        MapName mn = new MapName("天王盖地虎","宝塔镇河妖");
        nick.put("小虎", mn);
        mcp.setNicks(nick);
        exec("MapComPerson.hbm.xml", mcp);
    }

    执行上面的测试类,发现在mysql中,当集合属性为组件的时候,Hibernate将集合属性放在单独表中,用外键关联主表,并将属性值映射成单独表中的列。

     person_inf

     nick_inf

    组件作为map的索引(key)

    对于集合类型,其key不仅可以是普通数据类型或者包装类型,例如String等,也可以是组件类型。Hibernate中使用<composite-map-key>来映射复合型的key。即每一个key又是另一种复合类的对象。这些复合类又会有自己的属性,

    根据key复合类属性的类型,<composite-map-key>标签下又可以有两种子标签:

    <key-property>,复合类属性为普通类型的数据,或者日期,字符串等。

    <key-many-to-one>复合类属性引用了其他持久化类。

    下面演示以组件作为map的索引,还是以person类为例,假如person类中有一个属性nickPower是map类型,其索引(key)的类型是Name,

     1 package com;
     2 
     3 import java.util.HashMap;
     4 import java.util.Map;
     5 
     6 public class MapKeyPerson {
     7     public Integer getId() {
     8         return id;
     9     }
    10     public void setId(Integer id) {
    11         this.id = id;
    12     }
    13     public int getAge() {
    14         return age;
    15     }
    16     public void setAge(int age) {
    17         this.age = age;
    18     }
    19     
    20     public Map<MapKeyName, Integer> getNickPower() {
    21         return nickPower;
    22     }
    23     public void setNickPower(Map<MapKeyName, Integer> nickPower) {
    24         this.nickPower = nickPower;
    25     }
    26 
    27     private Integer id;
    28     private int age;
    29     private Map<MapKeyName, Integer> nickPower = new HashMap<MapKeyName, Integer>();
    30     
    31 }

    这里的MapKeyName也只是一个普通的类,但是因为会作为Map集合的索引,所以必须以first和last这两个关键属性重写equals()和hashCode()两个方法,才能保证Map的正常工作

     1 package com;
     2 
     3 public class MapKeyName {
     4     public String getFirst() {
     5         return first;
     6     }
     7     public void setFirst(String first) {
     8         this.first = first;
     9     }
    10     public String getLast() {
    11         return last;
    12     }
    13     public void setLast(String last) {
    14         this.last = last;
    15     }
    16     public Person getOwner() {
    17         return owner;
    18     }
    19     public void setOwner(Person owner) {
    20         this.owner = owner;
    21     }
    22     private String first;
    23     private String last;
    24     private Person owner;
    25     public MapKeyName() {
    26         
    27     }
    28     public MapKeyName(String first, String last) {
    29         this.first = first;
    30         this.last = last;
    31     }
    32     
    33     public boolean equals(Object obj) {
    34         if (this == obj) return true;
    35         if (obj != null && obj.getClass() == MapKeyName.class) {
    36             MapKeyName target = (MapKeyName)obj;
    37             if (target.getFirst().equals(getFirst())
    38                 && target.getLast().equals(getLast())) {
    39                     return true;
    40                 }
    41         }
    42         return false;
    43     }
    44     
    45     public int hashCode() {
    46         return getFirst().hashCode() * 13 + getLast().hashCode();
    47     }
    48 }

     Person类的映射文件,

     1 <?xml version="1.0"  encoding="UTF-8"?>    
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
     4 
     5 <hibernate-mapping package="com">
     6     <class name="MapKeyPerson" table="person_inf">
     7         <id name="id" column="person_id" type="int">
     8             <generator class="identity" />
     9         </id>
    10         <property name="age" type="int" />
    11         <map name="nickPower" table="nick_Power">
    12             <key column="person_id" not-null="true" />
    13             <!-- 因为may-key是复合类型,所以使用下面元素 -->
    14             <composite-map-key class="MapKeyName">
    15                 <key-property name="first" type="string" />
    16                 <key-property name="last" type="string" />
    17             </composite-map-key>
    18             <element column="nick_power" type="int" />
    19         </map>
    20     </class>
    21 </hibernate-mapping>

     在测试类中新增测试方法mapKeyTest(),

     1 public static void mapKeyTest() {
     2     MapKeyPerson mkp = new MapKeyPerson();
     3     mkp.setAge(25);
     4     Map<MapKeyName, Integer> nickPower = new HashMap<MapKeyName, Integer>();
     5     MapKeyName mkn = new MapKeyName();
     6     mkn.setFirst("天王盖地虎");
     7     mkn.setLast("宝塔镇河妖");
     8     nickPower.put(mkn, 100);
     9     mkp.setNickPower(nickPower);
    10     exec("MapKeyPerson.hbm.xml", mkp);
    11 }

    执行上面的测试类,会发现Hibernate已经将MapKeyName组件的各种属性都映射到了集合属性表的各个列了,此时MapKeyName属性将作为map key使用,hibernate将外键列,MapKeyName各个属性一起作为联合主键。

     person_inf

     nick_power

     nick_power表中的联合主键

    组件作为复合主键

    上面的持久化类的主键通常都是普通数据类型,如 private int id, 主键也可以是复合类型,即以组件作为主键。那么在映射文件中,就以<composite-id>来映射,在<composite-id>标签下以<key-property>来映射组件属性。

    同时,因为主键将使用一个组件类型来代替,这个组件类型需要实现 java.io.Serializable 接口,

    例如在下面的持久化类中,用复合类型的name作为主键,

     1 package com;
     2 
     3 public class PrimaryKeyPerson {
     4     public int getAge() {
     5         return age;
     6     }
     7     public void setAge(int age) {
     8         this.age = age;
     9     }
    10 
    11     public PrimaryKeyName getName() {
    12         return name;
    13     }
    14     public void setName(PrimaryKeyName name) {
    15         this.name = name;
    16     }
    17 
    18     private Integer id;
    19     private int age;
    20     private PrimaryKeyName name;
    21     
    22 }

    此复合类PrimaryKeyName也需要重写equals()和hashCode()方法(以first和last为关键属性),这个组件类型需要实现 java.io.Serializable 接口,

     1 package com;
     2 
     3 public class PrimaryKeyName implements java.io.Serializable {
     4     public String getFirst() {
     5         return first;
     6     }
     7     public void setFirst(String first) {
     8         this.first = first;
     9     }
    10     public String getLast() {
    11         return last;
    12     }
    13     public void setLast(String last) {
    14         this.last = last;
    15     }
    16     private String first;
    17     private String last;
    18     public PrimaryKeyName() {}
    19     
    20     public PrimaryKeyName(String first, String last) {
    21         this.first = first;
    22         this.last = last;
    23     }
    24     
    25     public boolean equals(Object obj) {
    26         if (this == obj) return true;
    27         if (obj != null && obj.getClass() ==  PrimaryKeyName.class) {
    28             PrimaryKeyName target = (PrimaryKeyName)obj;
    29             return target.getFirst().equals(getFirst()) && target.getLast().equals(getLast());
    30         }
    31         return false;
    32     }
    33     
    34     public int hashCode() {
    35         return this.getFirst().hashCode() * 7 + this.getLast().hashCode();
    36     }
    37 
    38 }

    person类的映射文件如下,用<composite-id>映射复合组件为主键,用子元素<key-property>映射复合组件中的属性,

     1 <?xml version="1.0"  encoding="UTF-8"?>    
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
     4 
     5 <hibernate-mapping package="com">
     6     <class name="PrimaryKeyPerson" table="Person_inf">
     7         <composite-id name="name" class="PrimaryKeyName">
     8             <key-property name="first" type="string" />
     9             <key-property name="last" type="string" />
    10         </composite-id>
    11         <property name="age" type="int" />
    12     </class>
    13 </hibernate-mapping>

    在测试类中新增测试方法,PrimaryKeyTest(),

    1 public static void PrimaryKeyTest() {
    2     PrimaryKeyPerson pkp = new PrimaryKeyPerson();
    3     PrimaryKeyName name = new PrimaryKeyName();
    4     name.setFirst("天王盖地虎");
    5     name.setLast("宝塔镇河妖");
    6     pkp.setAge(20);
    7     pkp.setName(name);
    8     exec("PrimaryKeyPerson.hbm.xml", pkp);
    9 }

    执行上面的测试代码,发现Hibernate将PrimaryKeyName组件的所有属性映射为person类的列,成为person表的联合主键,

    person_inf

     person_inf表的联合主键。

    多列作为联合主键

    如果将持久化类中的多列作为联合主键,hibernate也用<composite-id>来映射,同时持久化类本身需要实现 java.io.Serializable接口,情形与上面的组件为复合主键非常类似,

    假如person类中以first和last作为联合主键,首先要让person类实现 java.io.Serializable接口,并且重写equals和hashCode方法,

     1 package com;
     2 
     3 public class UnionKeyPerson implements java.io.Serializable {
     4     private String first;
     5     private String last;
     6     private int age;
     7     
     8     public String getFirst() {
     9         return first;
    10     }
    11     public void setFirst(String first) {
    12         this.first = first;
    13     }
    14     public String getLast() {
    15         return last;
    16     }
    17     public void setLast(String last) {
    18         this.last = last;
    19     }
    20 
    21     public boolean equals(Object obj) {
    22         if (this == obj) return true;
    23         if (obj != null && obj.getClass() ==  PrimaryKeyName.class) {
    24             PrimaryKeyName target = (PrimaryKeyName)obj;
    25             return target.getFirst().equals(getFirst()) && target.getLast().equals(getLast());
    26         }
    27         return false;
    28     }
    29     
    30     public int hashCode() {
    31         return this.getFirst().hashCode() * 7 + this.getLast().hashCode();
    32     }
    33     public int getAge() {
    34         return age;
    35     }
    36     public void setAge(int age) {
    37         this.age = age;
    38     }
    39 
    40 }

     这种情况下就没有依赖的额外组件了,直接是持久化类和映射文件,映射文件如下,

     1 <?xml version="1.0"  encoding="UTF-8"?>    
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
     4 
     5 <hibernate-mapping package="com">
     6     <class name="UnionKeyPerson" table="Person_inf">
     7         <composite-id>
     8             <key-property name="first" type="string" />
     9             <key-property name="last" type="string" />
    10         </composite-id>
    11         <property name="age" type="int" />
    12     </class>
    13 </hibernate-mapping>

    映射文件也与前面的组件为联合主键非常类似,只不过这里的<composite-id>不需要额外映射组件类了,而是直接用持久化类中的属性,因此不再需要name和class标签了。

    在测试类中新增UnionKeyTest()方法,

    1 public static void UnionKeyTest() {
    2     UnionKeyPerson ukp = new UnionKeyPerson();
    3     ukp.setFirst("天王盖地虎");
    4     ukp.setLast("宝塔镇河妖");
    5     ukp.setAge(30);
    6     exec("UnionKeyPerson.hbm.xml",ukp);
    7 }

    执行测试类,表结构与上面的完全相同,这里将以属性first和last作为联合主键,

    使用JPA Annotation标注实体

    在实际应用中,使用Annotation代替XML映射文件的情形更多,因为使用XML文件需要维护两个文件,而使用Annotation只需要维护一个文件。这些Annotation是JPA标准,与Hibernate无关,具体要求可以参考JavaEE规范的API。

    如果将前面的person类改成Annotation方式来映射,将会是下面这样,

    @Entity用来标注该类是一个持久化类,

    @EmbeddedId用来标注复合类型的标识属性

    @EmbeddedId用来标注组件属性

     1 package com;
     2 
     3 import javax.persistence.AttributeOverride;
     4 import javax.persistence.AttributeOverrides;
     5 import javax.persistence.Column;
     6 import javax.persistence.Embedded;
     7 import javax.persistence.EmbeddedId;
     8 import javax.persistence.Entity;
     9 import javax.persistence.Table;
    10 
    11 @Entity
    12 @Table(name="person_table")
    13 public class AnnotationPerson {
    14     @EmbeddedId
    15     @AttributeOverrides({
    16         @AttributeOverride(name="first", column=@Column(name="person_first")),
    17         @AttributeOverride(name="last", column=@Column(name="person_last", length=20))
    18     })
    19     private AnnotationName name;
    20     @Column(name="person_email")
    21     private String email;
    22     @Embedded
    23     @AttributeOverrides({
    24         @AttributeOverride(name="name", column=@Column(name="cat_name", length=35)),
    25         @AttributeOverride(name="color", column=@Column(name="cat_color"))
    26     })
    27     private AnnotationCat pet;
    28     public AnnotationName getName() {
    29         return name;
    30     }
    31     public void setName(AnnotationName name) {
    32         this.name = name;
    33     }
    34     public String getEmail() {
    35         return email;
    36     }
    37     public void setEmail(String email) {
    38         this.email = email;
    39     }
    40     public AnnotationCat getPet() {
    41         return pet;
    42     }
    43     public void setPet(AnnotationCat pet) {
    44         this.pet = pet;
    45     }
    46 }

    上面持久化类中的name属性是一个组件属性,需要定义这个属性,在组件类名上面加上@Embeddable注解即可。

     1 package com;
     2 
     3 import javax.persistence.Embeddable;
     4 
     5 @Embeddable
     6 public class AnnotationName implements java.io.Serializable {
     7     private String first;
     8     private String last;
     9     
    10     public String getFirst() {
    11         return first;
    12     }
    13     public void setFirst(String first) {
    14         this.first = first;
    15     }
    16     public String getLast() {
    17         return last;
    18     }
    19     public void setLast(String last) {
    20         this.last = last;
    21     }
    22     public AnnotationName() {}
    23     public AnnotationName(String first, String last) {
    24         this.first = first;
    25         this.last = last;
    26     }
    27     public boolean equals(Object obj) {
    28         if (this == obj) return true;
    29         if (obj != null && obj.getClass() ==  PrimaryKeyName.class) {
    30             PrimaryKeyName target = (PrimaryKeyName)obj;
    31             return target.getFirst().equals(getFirst()) && target.getLast().equals(getLast());
    32         }
    33         return false;
    34     }
    35     public int hashCode() {
    36         return this.getFirst().hashCode() * 17 + this.getLast().hashCode();
    37     }
    38 
    39 }

    上面的pet也是一个属性组件,同样需要定义这个类,跟前面的name属性一样,

     1 package com;
     2 
     3 import javax.persistence.Embeddable;
     4 
     5 @Embeddable
     6 public class AnnotationCat {
     7     public AnnotationCat() {}
     8     public AnnotationCat(String name, String color) {
     9         this.name = name;
    10         this.color = color;
    11     }
    12     private String name;
    13     public String getName() {
    14         return name;
    15     }
    16     public void setName(String name) {
    17         this.name = name;
    18     }
    19     public String getColor() {
    20         return color;
    21     }
    22     public void setColor(String color) {
    23         this.color = color;
    24     }
    25     private String color;
    26 }

    有了上面这些持久化类和组件类之后即注解之后,就不再需要额外的映射文件了,在hibernate.cfg.xml中,

    可以用<mapping class="xxxx/AnnotationPerson" />来加载持久化类,当然也可以直接在java代码中,用addAnnotatedClass()方法直接加载带注解的持久化类,

    下面在测试类中新增测试方法annotationTest(),

     1 public static void annotationTest() {
     2     AnnotationPerson ap = new AnnotationPerson();
     3     ap.setEmail("xxx@baidu.com");
     4     AnnotationName name = new AnnotationName();
     5     name.setFirst("天王盖地虎");
     6     name.setLast("宝塔镇河妖");
     7     ap.setName(name);
     8     AnnotationCat pet = new AnnotationCat();
     9     pet.setName("miaomiao");
    10     pet.setColor("black");
    11     ap.setPet(pet);
    12     
    13     Configuration conf = new Configuration().configure();
    14     conf.addAnnotatedClass(AnnotationPerson.class);
    15     SessionFactory sf = conf.buildSessionFactory();
    16     Session sess = sf.openSession();
    17     Transaction tx = sess.beginTransaction();
    18     sess.save(ap);
    19     tx.commit();
    20     sess.close();
    21     sf.close();
    22 }

    执行测试类,可以看到hibernate将组件属性映射为表中的不同列了,并将name属性作为了联合主键,其效果跟用XML实现的映射文件完全一样。

    person_table

    person_table表结构

  • 相关阅读:
    自定义标签
    ssm学习的第一个demo---crm(1)
    xml文件中的${}
    Mybatis的回顾学习
    Mapper的.xml文件的delete的参数问题
    mybatis中xml文件的${}和#{}区别
    Mybatis:通过MapperScannerConfigurer进行mapper扫描
    Spring的applicationContext.xml的疑问解析
    Spring MVC 的springMVC.xml疑问解析
    【剑指 Offer】04.二维数组中的查找
  • 原文地址:https://www.cnblogs.com/fysola/p/6248579.html
Copyright © 2011-2022 走看看