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表结构

 

posted @ 2017-01-04 14:34  fysola  阅读(1124)  评论(0编辑  收藏  举报