Hibernate多对多关系映射
来源:互联网 发布:vue.js radio checked 编辑:程序博客网 时间:2024/05/22 17:36
多对多关系并不是两张表的关系,而是三张表的关系,而且要求必须有一个中间表,中间表必须只有两个字段,必须为复合主键,必须包含外键。
如果以上条件都满足,MyEclipse在三张表一起选择时,就可以生成多对多关系映射。
类一般只生成两个类,例如:学生选课中,只生成学生和课程类,关系使用以下方式描述:
1) 学生类中保存着该学生选择的所有课程对象,使用Set集合来保存。
2) 课程类中保存着所有选择此课程的学生对象,使用Set集合来保存。
建立数据表
CREATE TABLE user_course (
userid varchar2(40) ,
course_id number(8) ,
primary key (userid,course_id) ,
foreign key (userid) references t_user (userid)on delete cascade ,
foreign key (course_id) references course (id)on delete cascade
);
使用t_user,course和user_course表,完成映射:
many to many 前面打勾:
由于t_user使用assigned,course使用increment,因此,这里不统一选择方式。
而是在后面单独选择。
同时,注意将允许使用多对多的多选框选中。
可以在这里单独选择方式。
public class TUser implements java.io.Serializable {
private Stringuserid;
private StringrealName;
private Stringpassword;
private DateregistDate;
private DatelastLoginDate;
private Set courses = new HashSet(0);
public class Course implements java.io.Serializable {
private Integerid;
private Stringtitle;
private Set TUsers = newHashSet(0);
类中确定了集合关系
映射文件里也描述了多对多关系:
<?xmlversion="1.0"encoding="utf-8"?>
<!DOCTYPEhibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<classname="org.liky.pojo.TUser"table="T_USER"schema="SUNXUN">
<idname="userid"type="java.lang.String">
<columnname="USERID"length="40"/>
<generatorclass="assigned"></generator>
</id>
<propertyname="realName"type="java.lang.String">
<columnname="REAL_NAME"length="20"not-null="true"/>
</property>
<propertyname="password"type="java.lang.String">
<columnname="PASSWORD"length="32"not-null="true"/>
</property>
<propertyname="registDate"type="java.util.Date">
<columnname="REGIST_DATE"length="7"/>
</property>
<propertyname="lastLoginDate"type="java.util.Date">
<columnname="LAST_LOGIN_DATE"length="7"/>
</property>
<!--
在User中包含一个名称为courses的Set集合,数据是根据中间表USER_COURSE来关联取得的.
-->
<setname="courses"table="USER_COURSE"schema="SUNXUN">
<!--
中间表中通过USERID与当前类(User)关联
-->
<key>
<columnname="USERID"length="40"not-null="true"/>
</key>
<!--
中间表还通过COURSE_ID与Course对象关联,联系起来出现的是多对多关系。
-->
<many-to-manyentity-name="org.liky.pojo.Course">
<columnname="COURSE_ID"precision="8"scale="0"not-null="true"/>
</many-to-many>
</set>
</class>
</hibernate-mapping>
<?xmlversion="1.0"encoding="utf-8"?>
<!DOCTYPEhibernate-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>
<classname="org.liky.pojo.Course"table="COURSE"schema="SUNXUN">
<idname="id"type="java.lang.Integer">
<columnname="ID"precision="8"scale="0"/>
<generatorclass="increment"></generator>
</id>
<propertyname="title"type="java.lang.String">
<columnname="TITLE"length="50"not-null="true"/>
</property>
<setname="TUsers"inverse="true"table="USER_COURSE"schema="SUNXUN">
<key>
<columnname="COURSE_ID"precision="8"scale="0"not-null="true"/>
</key>
<many-to-manyentity-name="org.liky.pojo.TUser">
<columnname="USERID"length="40"not-null="true"/>
</many-to-many>
</set>
</class>
</hibernate-mapping>
可以发现有一边的配置中出现了inverse=”true”,这个配置表示关联关系由对方进行维护。
多对多关系中,实际上,关联关系指的就是中间表,需要根据业务想清楚谁来维护中间表,这里实现的功能是学生选课,也就是说学生是主动的一方,应该由学生添加自己所选的课程,也就是说中间表数据应该由学生来维护的。
因此可以说,关联关系应该由学生来维护,对于课程来说,关联关系就应该由对方(学生)来进行维护。
public static void main(String[] args) {
// 学生选课操作实际上是对学生的修改操作,而不是添加.
// 先取得一个学生
TUser user = (TUser) HibernateSessionFactory.getSession().get(
TUser.class,"zhangsan");
// // 以下int值就是该学生选择的课程编号
// int[] courseIds = { 2, 4, 5 };
// // 将课程id关联到学生对象中
// for (int i = 0; i < courseIds.length; i++) {
// int id = courseIds[i];
// Course c = new Course();
// c.setId(id);
// // 把课程加入到学生选择的课程集合里
// user.getCourses().add(c);
// }
// 如果想取消这些课程,直接将集合清空
user.getCourses().clear();
// 取消一部分,再添加一部分
int[] courseIds = { 2, 3,5 };
// 将课程id关联到学生对象中
for (int i = 0; i < courseIds.length; i++) {
int id = courseIds[i];
Course c = new Course();
c.setId(id);
// 把课程加入到学生选择的课程集合里
user.getCourses().add(c);
}
// 调用学生的修改
HibernateSessionFactory.getSession().update(user);
Transaction tx = HibernateSessionFactory.getSession()
.beginTransaction();
tx.commit();
HibernateSessionFactory.closeSession();
}
多对多关系应用——选课功能
首先,先要实现用户的登陆功能,当用户登陆后,列出所有课程供用户选择。
登陆功能之前已经实现过了,因此直接将后台代码拷贝过来即可。
登陆同时,注意,需要将之前选择的课程内容取得,并保存到user里。
public class TUserDAOImpl implements ITUserDAO {
public boolean isLogin(TUser user) throws Exception {
String hql = "FROM TUser AS u WHERE u.userid = ? AND u.password = ?";
Query query = HibernateSessionFactory.getSession().createQuery(hql);
query.setString(0, user.getUserid());
query.setString(1, user.getPassword());
List<User> allUser = query.list();
if (allUser !=null && allUser.size() > 0) {
// 登陆成功
// 取得查询的结果
TUser result = (TUser) allUser.get(0);
// 根据引用传递,将值设置到传入的user中
user.setRealName(result.getRealName());
user.setRegistDate(result.getRegistDate());
user.setLastLoginDate(result.getLastLoginDate());
// 将用户之前选择过的课程取得
user.setCourses(result.getCourses());
return true;
}
return false;
}
}
登陆成功后,用户可以看到选课的连接,点这个连接,进入选课页面,选课前,需要先查询出所有课程,列表显示。
<ahref="tuser!selectCoursePre.action">选课</a>
编写Action的方法,在这里查询所有课程信息。
public String selectCoursePre()throws Exception {
allCourse = ServiceFactory.getITUserServiceInstance().selectCoursePre();
return"select";
}
<resultname="select">/pages/user/user_select_course.jsp</result>
页面显示所有课程列表,通过多选框让用户选择。
<center>
用户登陆成功,当前登陆用户为: ${user.realName}
<br/>
<hr/>
<br/>
<s:formaction="tuser!selectCourse.action"method="post"namespace="/"theme="simple">
可选课程:<s:checkboxlistlist="allCourse"listKey="id"listValue="title"name="courseIds"></s:checkboxlist>
<br/>
<s:submitvalue="提交"></s:submit>
</s:form>
</center>
提交后,完成User的修改操作,注意,需要将课程信息合并到User对象里。
public String selectCourse()throws Exception {
// 先取得当前登陆用户信息
TUser loginUser = (TUser) ServletActionContext.getRequest()
.getSession().getAttribute("user");
// 设置该用户选择的课程
loginUser.getCourses().clear();
for (int i = 0; i <courseIds.length; i++) {
int id =courseIds[i];
Course c = new Course();
c.setId(id);
// 将课程合并到User对象中
loginUser.getCourses().add(c);
}
ServiceFactory.getITUserServiceInstance().selectCourse(loginUser);
// 将用户信息保存回Session
ServletActionContext.getRequest().getSession().setAttribute("user",
loginUser);
return"forward";
}
<resultname="forward">/forward.jsp</result>
测试时,提示懒汉式异常,也需要通过设置lazy解决。
<setname="courses"lazy="false" table="USER_COURSE"schema="SUNXUN">
使用时发现用户体验不好,用户无法看到当前选了哪些课程,而且没有默认选中已经选择过的课程。
在suc.jsp中显示出当前的课程。
当前选择的课程有:
<br/>
<fontcolor="red">
<c:forEachvar="c"items="${user.courses}">
${c.title } <br/>
</c:forEach>
</font>
<hr/>
注意,在映射文件中,最好加入order-by,防止顺序改变
<setname="courses"lazy="false"order-by="course_id"table="USER_COURSE"schema="SUNXUN">
最后,设置默认选中已经选择的课程。
需要在选择课程之前,先取得之前选的课程信息的id值,传递到页面上。
public String selectCoursePre()throws Exception {
allCourse = ServiceFactory.getITUserServiceInstance().selectCoursePre();
// 取得当前已经选择的课程信息
TUser loginUser = (TUser) ServletActionContext.getRequest()
.getSession().getAttribute("user");
Set<Course> allSelectedCourse = loginUser.getCourses();
if (allSelectedCourse !=null) {
Iterator<Course> iter = allSelectedCourse.iterator();
courseIds = new int[allSelectedCourse.size()];
int index = 0;
while (iter.hasNext()) {
Course c = iter.next();
courseIds[index++] = c.getId();
}
}
return"select";
}
如果使用普通标签,则必须使用下面两层循环的形式完成
<formaction="tuser!selectCourse.action"method="post">
可选课程:
<c:forEachvar="c"items="${allCourse}">
<inputtype="checkbox"name="courseIds"value="${c.id }"
<c:forEachvar="id"items="${courseIds}">
${id == c.id?"checked":"" }
</c:forEach>
/> ${c.title }
</c:forEach>
<br/>
<input type="submit" value="提交">
</form>
- Hibernate关系映射之多对多关系
- Hibernate对象关系映射-- 多对多关联关系映射
- Hibernate映射关系之多对多关系映射
- Hibernate对象关系映射详解之一对多关系映射
- Hibernate的关系映射多对多
- hibernate之映射关系多对多
- hibernate 映射关系 多对多
- Hibernate多对多关系映射
- Hibernate映射关系-多对多
- Hibernate 多对多关系映射详解
- Java- Hibernate 多对多关系映射
- Hibernate 映射多对多关联关系
- hibernate多对多关系映射
- hibernate中多对多关系映射
- hibernate多对多映射关系
- Hibernate 映射多对多关联关系
- Hibernate关联关系映射---多对多
- Hibernate映射多对多关联关系
- SASS实现颜色卡动画
- MyBatis 注解(摘自MyBatis官方文档)
- java LinkedList
- Linux strace命令
- Java NIO入门学习(三)
- Hibernate多对多关系映射
- FreeMarker工具类,用来根据模板文件生成html文件,html字符串等
- 游绍兴偶感
- ExtJs 4.x 学习小记:隐藏panel的标题栏
- linux下显示桌面和快速切换
- debian 无法使用apt-get解决办法
- climits 中的符号变量
- 2014_03_20周四工作日志:不错的调试代码1
- Exercise 22:目前你学到了些什么?