以前在使用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 閱讀(3846) |
評論 (1) |
編輯 收藏