hibernate映射 —— 多对多映射

本文介绍Hibernate框架中实现多对多关系映射的方法,包括数据库表结构设计、Pojo类及映射文件配置,并通过具体代码示例展示了如何完成学生选课功能。
讲解完一对多映射之后,做了一个简单的项目,其实说简单也不算简单了,以前都是一天做一个模块,感觉还是挺轻松的,但是现在忽然一天要完成2~3个模块,就觉得吃力了,而且是第一次做Hibernate就更觉得吃力了,不过吃力归吃力这些都不是现在逃避问题的理由,就像李兴华老师经常说的,既然都来学习了,就不要把任何话作为借口,自己就一心拼命往前走,而且现在也已经快拼到头了,我觉得挺不错,慢慢忍,我会好的,在网上很多人对技术的理解不一样,但是我就是跟MLDN的思路走,那些整天嚷着的理论我在MLDN一个都没落,都学了,还说理论上,受不了这些人。



§3.3 Hibernate 的多对多关系映射


多对多关系,表的结构为:

两个实体表,还包含一个关系表,关系表为复合主键,如果要在Hibernate中使用多对多关系映射,则关系表必须只包含两个字段,在hibernate中如果生成了多对多关系映射,则中间关系表不会生成实体(即没有对应的pojo类,更没有其映射文件)。



1、建立表


DROP TABLE user_course ;



DROP TABLE user ;



DROP TABLE course ;



CREATE TABLE user (

userid varchar(20) primary key ,

name varchar(20) not null ,

age int not null ,

birthday date not null

);



CREATE TABLE course (

id int primary key auto_increment ,

title varchar(50) not null,

description text not null,

course_num int not null

);



CREATE TABLE user_course (

userid varchar(20) ,

cid int ,

primary key (userid, cid ),

foreign key (userid) references user (userid) on delete cascade ,

foreign key (cid) references course (id) on delete cascade

);








2、生成映射
选择三个表一起生成映射

在选择主键生成方式的那一步需要注意:





然后每个表的主键生成方式,各自独立设置,即点击下一步再设置,对于中间表,不需要选择主键生成方式(参考复合主键映射)。



3、查看pojo类


生成好的pojo包含了多对多关系,而且没有生成中间关系表的映射。





package org.liky.pojo;



import java.util.Date;

import java.util.HashSet;

import java.util.Set;







public class User implements java.io.Serializable {



// Fields



private String userid;



private String name;



private Integer age;



private Date birthday;



private Set courses = new HashSet(0);



// Constructors





public User() {

}





public User(String userid, String name, Integer age, Date birthday) {

this.userid = userid;

this.name = name;

this.age = age;

this.birthday = birthday;

}





public User(String userid, String name, Integer age, Date birthday,

Set courses) {

this.userid = userid;

this.name = name;

this.age = age;

this.birthday = birthday;

this.courses = courses;

}



// Property accessors



public String getUserid() {

return this.userid;

}



public void setUserid(String userid) {

this.userid = userid;

}



public String getName() {

return this.name;

}



public void setName(String name) {

this.name = name;

}



public Integer getAge() {

return this.age;

}



public void setAge(Integer age) {

this.age = age;

}



public Date getBirthday() {

return this.birthday;

}



public void setBirthday(Date birthday) {

this.birthday = birthday;

}



public Set getCourses() {

return this.courses;

}



public void setCourses(Set courses) {

this.courses = courses;

}



}

package org.liky.pojo;



import java.util.HashSet;

import java.util.Set;







public class Course implements java.io.Serializable {



// Fields



private Integer id;



private String title;



private String description;



private Integer courseNum;



private Set users = new HashSet(0);



// Constructors





public Course() {

}





public Course(String title, String description, Integer courseNum) {

this.title = title;

this.description = description;

this.courseNum = courseNum;

}





public Course(String title, String description, Integer courseNum, Set users) {

this.title = title;

this.description = description;

this.courseNum = courseNum;

this.users = users;

}



// Property accessors



public Integer getId() {

return this.id;

}



public void setId(Integer id) {

this.id = id;

}



public String getTitle() {

return this.title;

}



public void setTitle(String title) {

this.title = title;

}



public String getDescription() {

return this.description;

}



public void setDescription(String description) {

this.description = description;

}



public Integer getCourseNum() {

return this.courseNum;

}



public void setCourseNum(Integer courseNum) {

this.courseNum = courseNum;

}



public Set getUsers() {

return this.users;

}



public void setUsers(Set users) {

this.users = users;

}



}



















































































4、查看并修改映射文件
重点注意 inverse和cascade



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

<class name="org.liky.pojo.User" table="user" catalog="testdb">

<id name="userid" type="java.lang.String">

<column name="userid" length="20" />

<generator class="assigned"></generator>

</id>

<property name="name" type="java.lang.String">

<column name="name" length="20" not-null="true" />

</property>

<property name="age" type="java.lang.Integer">

<column name="age" not-null="true" />

</property>

<property name="birthday" type="java.util.Date">

<column name="birthday" length="10" not-null="true" />

</property>

<!-- 与Course中的多对多关系配置相同,只是没有inverse=true的配置,表示由该类进行中间表操作。 -->

<set name="courses" table="user_course" catalog="testdb">

<key>

<column name="userid" length="20" not-null="true" />

</key>

<many-to-many entity-name="org.liky.pojo.Course">

<column name="cid" not-null="true" />

</many-to-many>

</set>

</class>

</hibernate-mapping>



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

<class name="org.liky.pojo.Course" table="course" catalog="testdb">

<id name="id" type="java.lang.Integer">

<column name="id" />

<generator class="native"></generator>

</id>

<property name="title" type="java.lang.String">

<column name="title" length="50" not-null="true" />

</property>

<property name="description" type="java.lang.String">

<column name="description" length="65535" not-null="true" />

</property>

<property name="courseNum" type="java.lang.Integer">

<column name="course_num" not-null="true" />

</property>

<!--

inverse="true"表示关系交给对方进行控制。

包含在Course类中表示关系由User类进行控制,也就是说,对User类进行操作时,会同时影响中间表的数据。

这里说的操作为(session.save()/update()/delete())



如果在这里加入了cascade,表示进行save()/update()/delete()操作时影响对方对象

在这里就是User类,不要与inverse混淆



table属性在这里表示两者关系维护的中间表



-->

<set name="users" inverse="true" table="user_course" catalog="testdb">

<key>

<!-- 表示中间表中的cid与当前Course中的主键值对应 -->

<column name="cid" not-null="true" />

</key>

<!-- 多对多关系映射,表示与User类有该关系映射 -->

<many-to-many entity-name="org.liky.pojo.User">

<!-- User类中的主键值与中间表的userid有对应关系 -->

<column name="userid" length="20" not-null="true" />

</many-to-many>

</set>

</class>

</hibernate-mapping>








5、完成DAO代码


6、测试选课和插入功能


UserDAO userdao = DAOFactory.getUserDAOInstance();

CourseDAO coursedao = DAOFactory.getCourseDAOInstance();



// 插入

// User user = new User();

// user.setUserid("Liky");

// user.setName("MLDN");

// user.setAge(21);

// user.setBirthday(new Date());

//

// try {

// userdao.doCreate(user);

// } catch (Exception e) {

// // TODO Auto-generated catch block

// e.printStackTrace();

// }

//

// Course c = new Course();

// c.setTitle("Hibernate基础");

// c.setDescription("框架基础(2)");

// c.setCourseNum(20);

//

// try {

// coursedao.doCreate(c);

// } catch (Exception e) {

// // TODO Auto-generated catch block

// e.printStackTrace();

// }



// 处理选课

try {

User user = userdao.findById("Liky");

// 先删除中间表的数据

user.setCourses(new HashSet());



// 取得课程数组

int[] cids = {1,2,3};



// 处理关系

for (int i = 0; i < cids.length;i++) {

Course c = new Course();

c.setId(cids[i]);

user.getCourses().add(c);

}

// 调用修改方法

userdao.doUpdate(user);





} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}




插入数据时,不会使用cascade插入对方数据

选课需要使用user的update方法进行处理,注意先清空原有课程,再加入新课程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值