以前在使用hibernate的时候,对“多对多”关联产生的关联表中数据修改起来很费尽,写这篇文章的目的是针对双向关联的多对多关系的关系表数据进行方便的增删的操作。如果各位高人已经有了更好的方法,请不吝赐教。
首先,我们定义两个实体。
Teacher和Student。它们是双向的多对多关系,Teacher是关系的维护端,Student是关系的被维护端。代码如下:
Teacher实体:
package com.wish.test.model;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
@Entity
@Table(name = "t_teacher")
public class Teacher implements java.io.Serializable
{
/**
*
*/
private static final long serialVersionUID = -8291865074665564287L;
@Id
@Column(name = "TeacherCode", length = 50)
private String teacherCode;
@Column(name = "TeacherName", length = 50)
private String teacherName;
@ManyToMany(mappedBy = "teachers", cascade = CascadeType.ALL)
private Map<String,Student> students = new HashMap<String,Student>();
public String getTeacherCode()
{
return teacherCode;
}
public void setTeacherCode(String teacherCode)
{
this.teacherCode = teacherCode;
}
public String getTeacherName()
{
return teacherName;
}
public void setTeacherName(String teacherName)
{
this.teacherName = teacherName;
}
public Map<String,Student> getStudents()
{
return students;
}
public void setStudents(Map<String,Student> students)
{
this.students = students;
}
public void addStudent(Student student)
{
if(!students.containsKey(student.getStudentCode()))
{
students.put(student.getStudentCode(), student);
}
}
public void removeStudent(Student student)
{
if(students.containsKey(student.getStudentCode()))
{
students.remove(student.getStudentCode());
System.out.println("remove student:" + student.getStudentName());
}
}
}
Student实体:
package com.wish.test.model;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
@Entity
@Table(name = "t_student")
public class Student implements java.io.Serializable
{
/**
*
*/
private static final long serialVersionUID = 9088096011898259042L;
@Id
@Column(name = "StudentCode", length = 50)
private String studentCode;
@Column(name = "StudentName", length = 50)
private String studentName;
@ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
@JoinTable(name = "t_student_teacher",
joinColumns = { @JoinColumn(name = "StudentCode", referencedColumnName = "studentCode") },
inverseJoinColumns = { @JoinColumn(name = "TeacherCode", referencedColumnName = "teacherCode") })
private Map<String,Teacher> teachers = new HashMap<String,Teacher>();
public String getStudentCode()
{
return studentCode;
}
public void setStudentCode(String studentCode)
{
this.studentCode = studentCode;
}
public String getStudentName()
{
return studentName;
}
public void setStudentName(String studentName)
{
this.studentName = studentName;
}
public Map<String,Teacher> getTeachers()
{
return teachers;
}
public void setTeachers(Map<String,Teacher> teachers)
{
this.teachers = teachers;
}
public void addTeacher(Teacher teacher)
{
if(!teachers.containsKey(teacher.getTeacherCode()))
{
this.teachers.put(teacher.getTeacherCode(), teacher);
}
}
public void removeTeacher(Teacher teacher)
{
if(teachers.containsKey(teacher.getTeacherCode()))
{
teachers.remove(teacher.getTeacherCode());
System.out.println("remove teacher:" + teacher.getTeacherName());
}
}
}
大家注意到Teacher和Student两个实体中都包含了添加和删除学生(教师)的方法:addStudent和removeStudent(addTeacher和removeTeacher),我们将用它们来进行对管理表数据的添加和修改操作。
第二,我们定义dao层。
IStudentDao和ITeacherDao,代码如下:
IStudentDao
package com.wish.test.dao;
import com.wish.test.model.Student;
public interface IStudentDao
{
public void insertStudent(Student student) throws RuntimeException;
public void updateStudent(Student student) throws RuntimeException;
public void deleteStudent(String studentCode) throws RuntimeException;
public Student getStudent(String studentCode) throws RuntimeException;
public Student loadTeachers(Student student) throws RuntimeException;
}
ITeacherDao
package com.wish.test.dao;
import com.wish.test.model.Teacher;
public interface ITeacherDao
{
public void insertTeacher(Teacher teacher) throws RuntimeException;
public void updateTeacher(Teacher teacher) throws RuntimeException;
public void deleteTeacher(String teacherCode) throws RuntimeException;
public Teacher getTeacher(String teacherCode) throws RuntimeException;
public Teacher loadStudents(Teacher teacher) throws RuntimeException;
}
它们的实现如下:
StudentDao
package com.wish.test.dao.impl;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import com.wish.test.dao.IStudentDao;
import com.wish.test.model.Student;
public class StudentDao implements IStudentDao
{
@PersistenceContext
private EntityManager em;
@Override
public void insertStudent(Student student) throws RuntimeException
{
em.persist(student);
}
@Override
public void deleteStudent(String studentCode) throws RuntimeException
{
em.remove(em.find(Student.class, studentCode));
}
@Override
public void updateStudent(Student student) throws RuntimeException
{
em.merge(student);
}
@Override
public Student getStudent(String studentCode) throws RuntimeException
{
return em.find(Student.class, studentCode);
}
@Override
public Student loadTeachers(Student student) throws RuntimeException
{
Student tempStudent = em.find(Student.class, student.getStudentCode());
if(tempStudent != null)
{
tempStudent.getTeachers().size();
}
return tempStudent;
}
}
TeacherDao
package com.wish.test.dao.impl;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import com.wish.test.dao.ITeacherDao;
import com.wish.test.model.Teacher;
public class TeacherDao implements ITeacherDao
{
@PersistenceContext
private EntityManager em;
@Override
public void insertTeacher(Teacher teacher) throws RuntimeException
{
em.persist(teacher);
}
@Override
public void deleteTeacher(String teacherCode) throws RuntimeException
{
em.remove(em.find(Teacher.class, teacherCode));
}
@Override
public void updateTeacher(Teacher teacher) throws RuntimeException
{
em.merge(teacher);
}
@Override
public Teacher getTeacher(String teacherCode) throws RuntimeException
{
return em.find(Teacher.class, teacherCode);
}
@Override
public Teacher loadStudents(Teacher teacher) throws RuntimeException
{
Teacher tempTeacher = em.find(Teacher.class, teacher.getTeacherCode());
if(tempTeacher != null)
{
tempTeacher.getStudents().size();
}
return tempTeacher;
}
}
第三,我们来定义Service层。
ITestService
package com.wish.test.service;
import com.wish.test.model.Student;
import com.wish.test.model.Teacher;
public interface ITestService
{
public void addStudent(Student student) throws RuntimeException;
public void modifyStudent(Student student) throws RuntimeException;
public void removeStudent(String studentCode) throws RuntimeException;
public void addTeacher(Teacher teacher) throws RuntimeException;
public void modifyTeacher(Teacher teacher) throws RuntimeException;
public void removeTeacher(String teacherCode) throws RuntimeException;
public Student getStudent(String studentCode) throws RuntimeException;
public Teacher getTeacher(String teacherCode) throws RuntimeException;
public Teacher loadStudents(Teacher teacher) throws RuntimeException;
public Student loadTeachers(Student student) throws RuntimeException;
}
其实现如下:
TestService
package com.wish.test.service.impl;
import org.springframework.transaction.annotation.Transactional;
import com.wish.test.dao.IStudentDao;
import com.wish.test.dao.ITeacherDao;
import com.wish.test.model.Student;
import com.wish.test.model.Teacher;
import com.wish.test.service.ITestService;
public class TestService implements ITestService
{
IStudentDao studentDao = null;
ITeacherDao teacherDao = null;
public TestService(IStudentDao studentDao, ITeacherDao teacherDao)
{
this.studentDao = studentDao;
this.teacherDao = teacherDao;
}
@Override
@Transactional(readOnly = false)
public void addStudent(Student student) throws RuntimeException
{
studentDao.insertStudent(student);
}
@Override
@Transactional(readOnly = false)
public void addTeacher(Teacher teacher) throws RuntimeException
{
teacherDao.insertTeacher(teacher);
}
@Override
@Transactional(readOnly = false)
public void removeStudent(String studentCode) throws RuntimeException
{
studentDao.deleteStudent(studentCode);
}
@Override
@Transactional(readOnly = false)
public void removeTeacher(String teacherCode) throws RuntimeException
{
teacherDao.deleteTeacher(teacherCode);
}
@Override
@Transactional(readOnly = false)
public void modifyStudent(Student student) throws RuntimeException
{
studentDao.updateStudent(student);
}
@Override
@Transactional(readOnly = false)
public void modifyTeacher(Teacher teacher) throws RuntimeException
{
teacherDao.updateTeacher(teacher);
}
@Override
@Transactional(readOnly = true)
public Student getStudent(String studentCode) throws RuntimeException
{
return studentDao.getStudent(studentCode);
}
@Override
@Transactional(readOnly = true)
public Teacher getTeacher(String teacherCode) throws RuntimeException
{
return teacherDao.getTeacher(teacherCode);
}
@Override
@Transactional(readOnly = true)
public Teacher loadStudents(Teacher teacher) throws RuntimeException
{
return teacherDao.loadStudents(teacher);
}
@Override
@Transactional(readOnly = true)
public Student loadTeachers(Student student) throws RuntimeException
{
return studentDao.loadTeachers(student);
}
}
第四,我们来定义调用service层的javabean,TestManage。
代码如下:
package com.wish.test.bean;
import org.apache.log4j.Logger;
import com.wish.spring.tools.SpringBeanController;
import com.wish.test.model.Student;
import com.wish.test.model.Teacher;
import com.wish.test.service.ITestService;
public class TestManage
{
private ITestService testService = (ITestService)SpringBeanController.getBean("testService");
private static Logger log = Logger.getLogger(TestManage.class);
public boolean addStudent(Student student)
{
try
{
testService.addStudent(student);
return true;
}
catch (RuntimeException e)
{
log.error(e.toString());
return false;
}
}
public boolean modifyStudent(Student student)
{
try
{
testService.modifyStudent(student);
return true;
}
catch (RuntimeException e)
{
log.error(e.toString());
return false;
}
}
public boolean removeStudent(String studentCode)
{
try
{
testService.removeStudent(studentCode);
return true;
}
catch (RuntimeException e)
{
log.error(e.toString());
return false;
}
}
public boolean addTeacher(Teacher teacher)
{
try
{
testService.addTeacher(teacher);
return true;
}
catch (RuntimeException e)
{
log.error(e.toString());
return false;
}
}
public boolean modifyTeacher(Teacher teacher)
{
try
{
testService.modifyTeacher(teacher);
return true;
}
catch (RuntimeException e)
{
log.error(e.toString());
return false;
}
}
public boolean removeTeacher(String teacherCode)
{
try
{
testService.removeTeacher(teacherCode);
return true;
}
catch (RuntimeException e)
{
log.error(e.toString());
return false;
}
}
public Student getStudent(String studentCode)
{
try
{
return testService.getStudent(studentCode);
}
catch (RuntimeException e)
{
log.error(e.toString());
return null;
}
}
public Teacher getTeacher(String teacherCode)
{
try
{
return testService.getTeacher(teacherCode);
}
catch (RuntimeException e)
{
log.error(e.toString());
return null;
}
}
public Teacher loadStudents(Teacher teacher)
{
try
{
return testService.loadStudents(teacher);
}
catch (RuntimeException e)
{
log.error(e.toString());
return null;
}
}
public Student loadTeachers(Student student)
{
try
{
return testService.loadTeachers(student);
}
catch (RuntimeException e)
{
log.error(e.toString());
return null;
}
}
}
最后,我们在JSP页面中调用javabean中的方法。
test.jsp,这些方法可以实现对双向多对多关联表数据的单条增删操作。
代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<jsp:useBean id="test" class="com.wish.test.bean.TestManage" scope="request"></jsp:useBean>
<%@page import="com.wish.test.model.Student"%>
<%@page import="com.wish.test.model.Teacher"%>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title></title>
</head>
<body>
<%
/**********************************************************************************
* 说明: *
* Student 和 Teacher 为两个实体,为多对多关系; *
* Teacher 为关系的维护端,Student为被维护端; *
* Teacher 与 Student 为级联添加关系; *
* 在Student存在addTeacher和removeTeacher方法; *
* 在Teacher存在addStudent和removeStudent方法; *
* 两个实体在数据库中对应的表中各存在10条记录,无关联数据 *
***********************************************************************************/
/* 添加关联 */
/* 从维护端添加与被维护端的关联
Teacher t = test.getTeacher("teacher01");
Student s1 = test.getStudent("student01");
Student s2 = test.getStudent("student02");
t = test.loadStudents(t);
s1 = test.loadTeachers(s1);
s2 = test.loadTeachers(s2);
t.addStudent(s1);
t.addStudent(s2);
s1.addTeacher(t);
s2.addTeacher(t);
test.modifyTeacher(t);
*/
/* 从被维护端添加与维护端的关联
Student s = test.getStudent("student03");
Teacher t2 = test.getTeacher("teacher02");
Teacher t3 = test.getTeacher("teacher03");
s = test.loadTeachers(s);
t2 = test.loadStudents(t2);
t3 = test.loadStudents(t3);
s.addTeacher(t2);
s.addTeacher(t3);
t2.addStudent(s);
t3.addStudent(s);
test.modifyStudent(s);
*/
/* 删除关联 */
/* 从维护端删除与被维护端的关联:目前这种对应模式,无法从维护端单条删除与被维护端的关联
Teacher t = test.getTeacher("teacher01");
Student s1 = test.getStudent("student01");
Student s2 = test.getStudent("student02");
t = test.loadStudents(t);
t.removeStudent(s1);
test.modifyTeacher(t);
*/
/* 从被维护端删除与维护端的关联
Student s = test.getStudent("student03");
Teacher t2 = test.getTeacher("teacher02");
Teacher t3 = test.getTeacher("teacher03");
s = test.loadTeachers(s);
s.removeTeacher(t2);
//s.removeTeacher(t3);
test.modifyStudent(s);
*/
// 直接删除维护端实体,关联删除了所有被维护端
//test.removeTeacher("teacher01");
// 直接删除被维护端实体,可以删除与维护端的关联************
//test.removeStudent("student11");
// 总结:对于不经常变动的实体,在定义其多对多关联时,尽量将其定义为被维护端,这样对其增加和修改关联时比较方便
%>
</body>
</html>
写的比较基础,请大家批评指正。
posted @
2008-07-26 08:45 licy 阅读(3843) |
评论 (1) |
编辑 收藏