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语句。