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 |
这时可以在程序中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语句。