之前介绍了Hibernate 映射简单集合属性,那么如果一个Bean内的属性不是简单类型,而是一个符合属性,Hibernate怎么处理?

比如一个User有一个Name属性,Name属性内部包含first和last两个属性。

hibernate.cfg.xml 不变,和之前的一样。

实体User:

package Model;

public class User {

private String uuid;
private Name name;
private String password;

public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Name getName() {
return name;
}
public void setName(Name name) {
this.name = name;
}

}

属性Name:

package Model;

public class Name {

private String first;
private String last;
private User owner;

public String getFirst() {
return first;
}
public void setFirst(String first) {
this.first = first;
}
public String getLast() {
return last;
}
public void setLast(String last) {
this.last = last;
}
public User getOwner() {
return owner;
}
public void setOwner(User owner) {
this.owner = owner;
}
}

2.User.hbm.xml:

</pre><pre name="code" class="html"><?xml version="1.0" encoding='GBK'?>    
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >

<hibernate-mapping package="Model">
<class name="User" table="user">
<id name="uuid" column="uuid">
<generator class="uuid"></generator>
</id>
<property name="password" column="password" type="java.lang.String"
length="16" />
<component name="name" class="Name">
<parent name="owner"/>
<property name="first"/>
<property name="last"/>
</component>
<!-- <set name="orders" table= "`order`" > -->
<!-- <key column="userid" not-null="true"></key> -->
<!-- <element type="java.lang.String" column="[order]" not-null="true"></element> -->
<!-- </set> -->

<!-- <list name="address" table="address"> -->
<!-- <key column="userid" not-null="true"></key> -->
<!-- <list-index column="list_"></list-index> -->
<!-- <element type="java.lang.String" column="address" not-null="true"></element> -->
<!-- </list> -->
</class>
</hibernate-mapping>

组件属性要用component元素来描述,name是属性名字,class书类名,parent是对引用者的引用。property属性来描述组件属性的属性。

3.测试类:

package Test;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import Model.Name;
import Model.User;


public class TestHibernate {

/**
* @param args
*/
public static void main(String[] args) {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tr = session.beginTransaction();
User user = new User();
Name name = new Name();
name.setFirst("Yao");
name.setLast("li");

user.setName(name);
session.save(user);

tr.commit();
session.close();
sessionFactory.close();
}
}

最终其实只会生成一张表,组件属性的内部属性被当作实体的基本属性看待。

如下图:

Hibernate 映射组件属性_hibernate




在看一种情况,如果Name属性中多了一个集合属性map怎么办呢?

那么要在component属性中添加map属性来描述这个集合即可。而且会多生成一张表,这个表的外键是主表的即User的主键,这个表的主键是外键和key的联合。

User实体不变,Name实体多了一个map,不写了。

User.hbm.xml:

<?xml version="1.0" encoding='GBK'?>    
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >

<hibernate-mapping package="Model">
<class name="User" table="user">
<id name="uuid" column="uuid">
<generator class="uuid"></generator>
</id>
<property name="password" column="password" type="java.lang.String"
length="16" />
<component name="name" class="Name">
<parent name="owner"/>
<property name="first"/>
<property name="last"/>
<map name="hobbies" table="hobbies_table">
<key column="f_person" not-null="true"></key>
<map-key column="`key`" type="string"></map-key>
<element column="`value`" type="int"></element>
</map>
</component>
<!-- <set name="orders" table= "`order`" > -->
<!-- <key column="userid" not-null="true"></key> -->
<!-- <element type="java.lang.String" column="[order]" not-null="true"></element> -->
<!-- </set> -->

<!-- <list name="address" table="address"> -->
<!-- <key column="userid" not-null="true"></key> -->
<!-- <list-index column="list_"></list-index> -->
<!-- <element type="java.lang.String" column="address" not-null="true"></element> -->
<!-- </list> -->
</class>
</hibernate-mapping>

如上是map的配置。

测试类:

package Test;

import java.util.HashMap;
import java.util.Map;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import Model.Name;
import Model.User;


public class TestHibernate {

/**
* @param args
*/
public static void main(String[] args) {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tr = session.beginTransaction();
User user = new User();
Name name = new Name();
name.setFirst("Yao");
name.setLast("li");

Map<String, Integer> h = new HashMap<String, Integer>();
h.put("one", 1);
h.put("two", 2);
h.put("three", 3);
name.setHobbies(h);
user.setName(name);
session.save(user);

tr.commit();
session.close();
sessionFactory.close();
}
}

最终的表结构:

Hibernate 映射组件属性_hibernate


Hibernate 映射组件属性_xml_03



总之在配置。hbm。xml文件的时候必须指定name,这里的name是用来扎到实体类的属性的,与。java文件一一对应。同时要指定column属性,这个与表中的列名一一对应。只有指明了类的属性和数据库的列名,才能建立一一映射。而在简单类型集合属性的配置时,需要在跟元素指定name和表名,在子元素中指定column。


最后再看一种情况,集合属性的元素是复合类型,比如user有一个nicks属性,它是一个存放许多Name类型的map

映射配置文件:

<?xml version="1.0" encoding='GBK'?>    
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >

<hibernate-mapping package="Model">
<class name="User" table="user">
<id name="uuid" column="uuid">
<generator class="uuid"></generator>
</id>
<property name="password" column="password" type="java.lang.String"
length="16" />
<map name="nicks" table="nicks_table">
<key column="userid" not-null="true"/>
<map-key column="`key`" type="string"/>
<composite-element class="Name">
<parent name="owner" />
<property name="first"/>
<property name="last"/>
</composite-element>
</map>
<!-- <set name="orders" table= "`order`" > -->
<!-- <key column="userid" not-null="true"></key> -->
<!-- <element type="java.lang.String" column="[order]" not-null="true"></element> -->
<!-- </set> -->

<!-- <list name="address" table="address"> -->
<!-- <key column="userid" not-null="true"></key> -->
<!-- <list-index column="list_"></list-index> -->
<!-- <element type="java.lang.String" column="address" not-null="true"></element> -->
<!-- </list> -->
</class>
</hibernate-mapping>

Name:

package Model;


public class Name {

private String first;
private String last;
private User owner;

public String getFirst() {
return first;
}
public void setFirst(String first) {
this.first = first;
}
public String getLast() {
return last;
}
public void setLast(String last) {
this.last = last;
}
public User getOwner() {
return owner;
}
public void setOwner(User owner) {
this.owner = owner;
}

}

User:

package Model;

import java.util.HashMap;
import java.util.Map;

public class User {

private String uuid;
private Map<String, Name> nicks = new HashMap<String, Name>();
private String password;

public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Map<String, Name> getNicks() {
return nicks;
}
public void setNicks(Map<String, Name> nicks) {
this.nicks = nicks;
}

}


测试:

package Test;

import java.util.HashMap;
import java.util.Map;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import Model.Name;
import Model.User;


public class TestHibernate {

/**
* @param args
*/
public static void main(String[] args) {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tr = session.beginTransaction();
User user = new User();
Name name = new Name();
name.setFirst("Yao");
name.setLast("li");

Name nick = new Name();
nick.setFirst("Yao1");
nick.setLast("li1");

Map<String, Name> h = new HashMap<String, Name>();
h.put("one", name);
h.put("two", nick);

user.setNicks(h);
session.save(user);

tr.commit();
session.close();
sessionFactory.close();
}
}

User实体配置时要使用map元素。同时指定name和table,复合元素的类型要在map子元素中指定。如果是简单类型就用element元素,但这里是复合类型name,那么就要用composite-element元素,指定class即可,剩下的和简单类型一样。