Hibernate Composite-element投射的一个简单例子

Hibernate Composite-element映射的一个简单例子

Hibernate Composite-element投射的一个简单例子

Composite-element映射非常类似于一对多的关系映射,配置Composite-element映射,可以实现简单的一对多关系。

本例中有一个团队(team)和成员(teammembers)表,每一个team都可以拥有多个teammembers,使用Composite-element映射能够完成这种需求。

建立两个相关的数据库表:

create table team(
id int(11) not null auto_increment,
name varchar(50) default null,
primary key(id)
)engine=innodb default charset=gbk;
create table teammembers(
team_id int(11) default null,
name varchar(20) default null,
age int(3) default null,
teamrole varchar(20) default null
)engine=innodb default charset=gbk;

建立实体类Team.java

package collect.composite_element;

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

public class Team implements java.io.Serializable {

	// Fields

	private Integer id;
	private String name;
	private Map memebers=new HashMap();

	// Constructors

	/** default constructor */
	public Team() {
	}

	/** full constructor */
	public Team(String name) {
		this.name = name;
	}

	// Property accessors

	public Integer getId() {
		return this.id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Map getMemebers() {
		return memebers;
	}

	public void setMemebers(Map memebers) {
		this.memebers = memebers;
	}

}

建立团队成员的实体类Member.java

package collect.composite_element;

import java.io.Serializable;

public class Member {
	private String id;
	private String name;
	private Team team;
	private String age;

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public Team getTeam() {
		return team;
	}

	public void setTeam(Team team) {
		this.team = team;
	}

}

建立一个映射文件Team.hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 
	Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
	<import class="collect.composite_element.Member" />
	<class name="collect.composite_element.Team" table="team"
		catalog="ssh">
		<id name="id" type="java.lang.Integer">
			<column name="id" />
			<generator class="native" />
		</id>
		<property name="name" type="java.lang.String">
			<column name="name" length="50" />
		</property>
		<map name="memebers" table="teammembers">
			<key column="team_id"></key>
			<map-key column="teamrole" type="java.lang.String"></map-key>
			<composite-element class="collect.composite_element.Member">
				<parent name="team" />
				<property name="name" />
				<property name="age"></property>
			</composite-element>
		</map>
	</class>
</hibernate-mapping>

“design”视图:

(:双击所有目录节点项,都会弹出”Properties”窗口,用来设置相应属性;在单击目录节点后,在右侧的属性设置窗口也可进行相应属性的设置,非常方便)

Hibernate Composite-element投射的一个简单例子

注解:映射文件中导入(import)Member类,使用了map集合映射,key指定了对应的keyteam_idmap-key则指定了Map集合元素的索引,这里是teamrole,即团队角色(这里假定角色不能重复,即key值唯一)。通过上面“design”视图,可以清楚地看到各属性层联关系。

使用composite-element元素(嵌于<map>标签内)Map集合中的每个元素映射给teammember的相应字段,这里映射了Member实体类。

<parent>子元素,用来表明composite-element类中的一个属性是指向包含它的实体的引用。如果在Member类中不去定义Team类型属性team及相应setter方法,运行时会出现异常:

Exception in thread "main"org.hibernate.PropertyNotFoundException: Could not find a setter for property team in classcollect.composite_element.Member

若同时去掉映射文件中的<parent>子元素,则一切与原来一样。这也说明了JVM要通过xml文件解析编译类文件。<parent>子元素只是起说明作用,对于此例因为没有用到get/setTeam(),故可省略掉。

将该映射文件加入到Hibernate配置文件中,建立一个测试类Test.java

package collect.composite_element;

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

import collect.map.UserMap;

public class Test {

	public static void main(String[] args) {
		// Configuration管理Hibernate配置
		Configuration config = new Configuration().configure();
		// 根据Configuration建立 SessionFactory
		// SessionFactory用来建立Session
		SessionFactory sessionFactory = config.buildSessionFactory();

		// 创建实例
		Team t=new Team();
		t.setName("team1");
		
		Member m1=new Member();
		m1.setName("m1");
		m1.setAge("33");
		Member m2=new Member();
		m2.setName("m2");
		m2.setAge("22");
		
		t.getMemebers().put("程序员", m1);
		t.getMemebers().put("测试工程师", m2);
		// 定义主键变量
		Integer pid;

		// 添加数据
		Session session = sessionFactory.openSession();
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			// 创建主键变量
			pid = (Integer) session.save(t);
			tx.commit();
		} catch (RuntimeException e) {
			if (tx != null)
				tx.rollback();
			throw e;
		} finally {
			session.close();
		}
		
		// 修改数据
		Member m3=new Member();
		m3.setName("增加人员");
		m3.setAge("33");
		session = sessionFactory.openSession();
		tx = null;
		try {
			tx = session.beginTransaction();
			t = (Team) session.get(Team.class, pid);
			// 修改名字
			t.setName("team update");
			t.getMemebers().put("项目经理", m3);
			t.getMemebers().remove("测试工程师");
			session.update(t);
			tx.commit();
		} catch (RuntimeException e) {
			if (tx != null)
				tx.rollback();
			throw e;
		} finally {
			session.close();
		}

		// 查询数据
		session = sessionFactory.openSession();
		t = (Team) session.get(Team.class, pid);
		System.out.println("team name:" + t.getName());
		System.out.println("member name:" + t.getMemebers());
		session.close();

		// 关闭sessionFactory
		sessionFactory.close();

	}

}

运行结果:

控制台:

13:38:45,751 DEBUG SQL:346 -insert into ssh.team (name) values (?)

13:38:45,782 DEBUG SQL:346 -insert into teammembers (team_id, teamrole, name, age) values (?, ?, ?, ?)

13:38:45,782 DEBUG SQL:346 - insert intoteammembers (team_id, teamrole, name, age) values (?, ?, ?, ?)

数据库:

运行添加模块:

Hibernate Composite-element投射的一个简单例子

-----------------------------

运行修改模块:

team:

id        name

1        team update

teammembers:

team_id    name    age    teamrole

1                  m1        33      程序员

1                  m3        33      项目经理