组件属性
如果持久化类的属性并不是基本数据类型,也不是一个日期或者字符串常量,而是一个复合类型的对象,例如 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表结构