现在的位置: 首页 > 综合 > 正文

11、haibernate映射map

2018年02月05日 ⁄ 综合 ⁄ 共 7521字 ⁄ 字号 评论关闭

haibernate映射map

对于对象属性中有Map类型的对象的映射,一个类如下含有Map类型:

1、map中为简单数据类型的:

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

public class Team
{
	private String id;
	
	private String teamName;
	
	private Map students = new HashMap();

	public String getId()
	{
		return id;
	}

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

	public String getTeamName()
	{
		return teamName;
	}

	public void setTeamName(String teamName)
	{
		this.teamName = teamName;
	}

	public Map getStudents()
	{
		return students;
	}

	public void setStudents(Map students)
	{
		this.students = students;
	}
	
}

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">

<hibernate-mapping>
	
	<class name="com.cdtax.hibernate.Team" table="team">
		
		<id name="id" column="id" type="string">
			<generator class="uuid">
			</generator>
		</id>
	
		
		
		<property name="teamName" column="teamname" type="string"></property>
		
		<map name="students" table="student">
			<key column="team_id"></key>
			<index column="name" type="java.lang.String"></index><!-- 指定Map中的key值 -->
			<element column="description" type="java.lang.String"></element><!-- 指定Map中的value值 -->
		</map>		 
	</class>
	
</hibernate-mapping>

对于此例子,成员变量Map为简单数据类型的,在映射文件中增加一个map标签,name属性仍然是成员变量名,多了一个table属性,指出此Map所要对应的表,也就是在数据库中要有一张表来存储Map的信息。map标签中要有一个key子标签,来指明Map类型的成员变量属于哪一个team,就是要在map所对应的表中有一列来标明team的标识,所以有个column属性,这里设定为team_id,对于Map映射,必须还要有一个index子标签,指出Map的key值,这里是name,还要有一个element子标签指出Map的value值,这里是description。element子标签只能有一个。对应关系图:

运行产生表的程序,结果:

create table student (team_id varchar(255) not null, description varchar(255), name varchar(255) not null, primary key (team_id, name))
create table team (id varchar(255) not null, teamname varchar(255), primary key (id))

可以看到student表的主键是team_id和name的联合主键,因为光是一个team_id或name无法具体确定一个map中的值。

一个save的测试:

import java.util.Map;

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

public class HibernateTest
{
	private static SessionFactory sessionFactory;
	
	static
	{
		try
		{
			sessionFactory = new Configuration().configure().buildSessionFactory();
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}
	
	public static void main(String[] args)
	{
				
		Session session = sessionFactory.openSession();
		Transaction tx = null;
		
		try
		{
			tx = session.beginTransaction();
			
			Team team = new Team();
			team.setTeamName("team 2");
			Map map = team.getStudents();
			map.put("lisi", "hello");
			map.put("zhangsan", "world");
			session.save(team);
			
			tx.commit();
		}
		catch(Exception ex)
		{
			if(null != tx)
			{
				tx.rollback();
			}
			ex.printStackTrace();
		}
		finally
		{
			session.close();
		}
	}
}

执行结果:

Hibernate: insert into team (teamname, id) values (?, ?)
Hibernate: insert into student (team_id, name, description) values (?, ?, ?)
Hibernate: insert into student (team_id, name, description) values (?, ?, ?)

2、对于map的值(value)为实体类型的

如果map的value为Student类型的,Student定义如下:

public class Student
{
	private String id;
	
	private String cardId;
	
	private String name;
	
	private int age;
	
	private Team team;

	public String getId()
	{
		return id;
	}

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

	public String getCardId()
	{
		return cardId;
	}

	public void setCardId(String cardId)
	{
		this.cardId = cardId;
	}

	public String getName()
	{
		return name;
	}

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

	public int getAge()
	{
		return age;
	}

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

	public Team getTeam()
	{
		return team;
	}

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

编写相应的映射文件:Student.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">

<hibernate-mapping>
	
	<class name="com.cdtax.hibernate.Student" table="student">
		
		<id name="id" column="id" type="string">
			<generator class="uuid">
			</generator>
		</id>
	
		
		
		<property name="cardId" column="card_id" type="string"></property>
		<property name="name" column="name" type="string"></property>
		<property name="age" column="age" type="integer"></property>
		
		<many-to-one name="team" column="team_id" class="com.cdtax.hibernate.Team" cascade="none" fetch="join"></many-to-one>	 
	</class>
	

对于Student.hbm.xml,学生与team是多对一的关系,所以使用了many-to-one

创建表:

create table student (id varchar(255) not null, card_id varchar(255), name varchar(255), age integer, team_id varchar(255), primary key (id))
create table team (id varchar(255) not null, teamname varchar(255), primary key (id))
alter table student add index FK8FFE823BB04F9E7 (team_id), add constraint FK8FFE823BB04F9E7 foreign key (team_id) references team (id)

编写一个测试类:

import java.util.Map;

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

public class HibernateTest
{
	private static SessionFactory sessionFactory;
	
	static
	{
		try
		{
			sessionFactory = new Configuration().configure().buildSessionFactory();
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}
	
	public static void main(String[] args)
	{
				
		Session session = sessionFactory.openSession();
		Transaction tx = null;
		
		try
		{
			tx = session.beginTransaction();
			
			Team team = new Team();
			team.setTeamName("team 2");
			Map map = team.getStudents();
			
			Student student1 = new Student();
			student1.setAge(20);
			student1.setName("zhang1111");
			student1.setTeam(team);
			
			Student student2 = new Student();
			student2.setAge(20);
			student2.setName("zhang222");
			student2.setTeam(team);
			
			Student student3 = new Student();
			student3.setAge(20);
			student3.setName("zhang333");
			student3.setTeam(team);
			session.save(team);
			
			map.put("111", student1);
			map.put("222", student2);
			map.put("333", student3);
			
			session.save(team);
			
			tx.commit();
		}
		catch(Exception ex)
		{
			if(null != tx)
			{
				tx.rollback();
			}
			ex.printStackTrace();
		}
		finally
		{
			session.close();
		}
	}
}

执行的结果:

Hibernate: insert into team (teamname, id) values (?, ?)
Hibernate: insert into student (card_id, name, age, team_id, id) values (?, ?, ?, ?, ?)
Hibernate: insert into student (card_id, name, age, team_id, id) values (?, ?, ?, ?, ?)
Hibernate: insert into student (card_id, name, age, team_id, id) values (?, ?, ?, ?, ?)
Hibernate: update student set team_id=?, card_id=? where id=?
Hibernate: update student set team_id=?, card_id=? where id=?
Hibernate: update student set team_id=?, card_id=? where id=?

这里要注意的是出现了三条update语句

通过程序,我们并没有设置student的cardId值,这个值是由Team来维护的,因为我们没在team中声明控制反转,所以Student在插入时没办法获得cardId值,由team在student插入后更新,就是update语句的由来。

修改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">

<hibernate-mapping>
	
	<class name="com.cdtax.hibernate.Team" table="team">
		
		<id name="id" column="id" type="string">
			<generator class="uuid">
			</generator>
		</id>
	
		
		
		<property name="teamName" column="teamname" type="string"></property>
		
		<map name="students" table="student" cascade="all" inverse="true">
			<key column="team_id"></key>
			<index column="card_id" type="java.lang.String"></index><!-- 指定Map中的key值 -->
			<one-to-many class="com.cdtax.hibernate.Student"/>
		</map>		 
	</class>
	
</hibernate-mapping>

增加了inverse=true,执行结果

Hibernate: insert into team (teamname, id) values (?, ?)
Hibernate: insert into student (card_id, name, age, team_id, id) values (?, ?, ?, ?, ?)
Hibernate: insert into student (card_id, name, age, team_id, id) values (?, ?, ?, ?, ?)
Hibernate: insert into student (card_id, name, age, team_id, id) values (?, ?, ?, ?, ?)

只有四条插入语句,没有了更新语句,但是我们到数据库中查看student表,发现结果:

402881c0423151660142315166d10002 null zhang222 20 402881c0423151660142315166c20001
402881c0423151660142315166d10003 null zhang1111 20 402881c0423151660142315166c20001
402881c0423151660142315166d10004 null zhang333 20 402881c0423151660142315166c20001

cardid列没有添加上去,为null值。

这时可以在程序中student中在进行set,就是:

			Student student1 = new Student();
			student1.setAge(20);
			student1.setName("zhang1111");
			student1.setCardId("1111");
			student1.setTeam(team);

但是这样做以后,我们保存的就是使用student.setCardId()设进去的值了,而

			map.put("111", student1);
			map.put("222", student2);
			map.put("333", student3);

这些语句的key就不起作用了,也就是说,如果我的student1.setCardId(‘“11111”),而我map.put(“aaaa”,student1),则保存的是1111,aaaa就没有用了,当然可以使用如下方法使其保持一致,就是:map.put(student1.getCardId(),student1);这样过于啰嗦,所以还是使用team维护关系,就是去掉inverse=true,虽然多了几条update语句。

抱歉!评论已关闭.