Mybatis中多对多映射详解
Mybatis中一对多映射详解
对于在mybatis中的多对多的处理,其实我们可以参照一对多来解决
【注意】在这个例子中有三个字段都是一样的:id,这种情况一定要小心,要给列起别名的(上面的一对一和一对多中如果出现这种情况也是一样的处理方式)1、建表语句:
drop table student_course;
drop table course;
drop table student;
如果需要可以使用 cascade constraints;
create table course (id number primary key,course_code varchar2(30) not null,course_name varchar2(30) not null);
create table student (id number primary key,name varchar2(10) not null,gender varchar2(10) ,major varchar2(10) ,grade varchar2(10));
create table student_course (id number primary key,student_id number references student(id),course_id number references course(id));
2、pojo类:
Course类实现
package com.mybatis.pojo;Student类实现:
import java.util.List;
public class Course {
private Integer id;
private String courseCode; // 课程编号
private String courseName;// 课程名称
private List<Student> students;// 选课学生
// get/set
public Course() {}
public Course(Integer id, String courseCode, String courseName) {
super();
this.id = id;
this.courseCode = courseCode;
this.courseName = courseName;
}
public Course(Integer id, String courseCode, String courseName,
List<Student> students) {
this.id = id;
this.courseCode = courseCode;
this.courseName = courseName;
this.students = students;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCourseCode() {
return courseCode;
}
public void setCourseCode(String courseCode) {
this.courseCode = courseCode;
}
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
@Override
public String toString() {
return "Course [id=" + id + ", courseCode=" + courseCode
+ ", courseName=" + courseName + ", students=" + students
+ "]";
}
}
package com.mybatis.pojo;在设置完上面的操作之后,我们进行配置mybatis-config.xml文件注册基本信息
import java.util.List;
public class Student {
private Integer id;
private String name; // 姓名
private String gender; // 性别
private String major; // 专业
private String grade; // 年级
private List<Course> courses;// 所选的课程
public Student(Integer id, String name, String gender,String major, String grade, List<Course> courses) {
super();
this.id = id;
this.name = name;
this.gender = gender;
this.major = major;
this.grade = grade;
this.courses = courses;
}
public Student(Integer id, String name, String gender, String major,
String grade) {
super();
this.id = id;
this.name = name;
this.gender = gender;
this.major = major;
this.grade = grade;
}
public Student() {
super();
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getMajor() {
return major;
}
public void setMajor(String major) {
this.major = major;
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
public List<Course> getCourses() {
return courses;
}
public void setCourses(List<Course> courses) {
this.courses = courses;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", gender="
+ gender + ", major=" + major + ", grade=" + grade
+ ", courses=" + courses + "]";
}
}
<?xml version="1.0" encoding="UTF-8"?> <!-- 进行dtd约束,其中-//mybatis.org//DTD Config 3.0//EN为公共约束, http://mybatis.org/dtd/mybatis-3-config.dtd为获取网络中提供的dtd约束 --><!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration> <typeAliases> <!-- 给pojo类起别名 --> <typeAlias type="com.mybatis.pojo.Student" alias="Student" /> <typeAlias type="com.mybatis.pojo.Course" alias="Course" /> </typeAliases> <!-- 配置数据库环境其中development为默认的数据库名称事务管理器transactionManager类型为JDBC类型,数据源dataSource使用连接池的方式 --> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <!-- 配置数据库信息这里使用oracle数据库 --> <property name="driver" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl" /> <property name="username" value="briup" /> <property name="password" value="briup" /> </dataSource> </environment> </environments> <!-- 配置xml文件映射路径,在这里可以进行sql的操作 --> <mappers> <mapper resource="com/mybatis/mappers/Many2ManyMapper.xml" /> </mappers></configuration>配置Many2ManyMapper接口:
package com.mybatis.mappers;配置Many2ManyMapper.xml:
import java.util.List;
import com.mybatis.pojo.Course;
import com.mybatis.pojo.Student;
public interface Many2ManyMapper {
//插入student数据
public void insertStudent(Student student);
//插入course数据
public void insertCourse(Course course);
//通过id查询学生
public Student selectStudentById(Integer id);
//通过id查询课程
public Course selectCourseById(Integer id);
//学生x选课y
public void studentSelectCourse(Integer id,Student student, Course course);
//查询比指定id值小的学生信息
public List<Student> getStudentByIdOnCondition(Integer id);
//查询student级联查询出所选的course并且组装成完整的对象
public Student getStudentByIdWithCourses(Integer id);
}
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!-- com.mybatis.mappers.StudentMapper是我们定义接口的全限定名字 这样就可以使用接口调用映射的SQL语句了 这个名字一定要和接口对应上 --><mapper namespace="com.mybatis.mappers.Many2ManyMapper"> <insert id="insertStudent" parameterType="Student"> insert into student values(#{id},#{name},#{gender},#{major},#{grade}) </insert> <insert id="insertCourse" parameterType="Course"> insert into course values(#{id},#{courseCode},#{courseName}) </insert> <select id="selectStudentById" parameterType="int" resultType="Student"> select * from student where id=#{id} </select> <select id="selectCourseById" parameterType="int" resultType="Course"> select id,course_code as courseCode,course_name courseName from course where id=#{id} </select> <insert id="studentSelectCourse"> <!-- param1代表方法中第一个参数 以此类推 --> insert into student_course(id,student_id,course_id) values (#{param1},#{param2.id},#{param3.id}) </insert> <!-- 如果有特殊符号的话 需要用 <![CDATA[ 特殊符号 ]]> 例如 < & 等等 --> <select id="getStudentByIdOnCondition" parameterType="int" resultType="Student"> <![CDATA[ select * from student where id < #{id} ]]> </select> <!-- 这里使用了嵌套结果ResultMap的方式进行级联查询,当然也可以使用嵌套查询select --> <!-- 映射一个基本的Student查询结果 --> <resultMap id="StudentResult" type="Student"> <id property="id" column="id"/> <result property="name" column="name"/> <result property="gender" column="gender"/> <result property="major" column="major"/> <result property="grade" column="grade"/> </resultMap> <!-- 继承上面那个基本的映射,再扩展出级联查询 --> <resultMap id="StudentResultWithCourses" type="Student" extends="StudentResult"> <collection property="courses" resultMap="CourseResult"></collection> </resultMap> <!-- 这里特别要是的是column="cid" 这是和select语句中的 c.id as cid对应的 一定一定一定要对应起来 --> <resultMap id="CourseResult" type="Course"> <id property="id" column="cid"/> <result property="courseCode" column="course_code"/> <result property="courseName" column="course_name"/> </resultMap> <!-- 注意:查询语句的中的c.id as cid这个地方,避免名字相同出现查询结果不正确的情况 同时在id="CourseResult"的resultMap中也有与这里对应的设置要特别特别注意 --> <select id="getStudentByIdWithCourses" parameterType="int" resultMap="StudentResultWithCourses"> select s.id,s.name,s.gender,s.major,s.grade,c.id as cid,c.course_code,c.course_name,sc.id,sc.student_id,sc.course_id from student s,course c,student_course sc where s.id=#{id} and s.id=sc.student_id and sc.course_id=c.id </select></mapper>测试代码:
package com.mybatis.test;import java.util.List;import org.apache.ibatis.session.SqlSession;import org.junit.Test;import com.mybatis.mappers.Many2ManyMapper;import com.mybatis.pojo.Course;import com.mybatis.pojo.Student;import com.mybatis.utils.MyBatisSqlSessionFactory;public class Many2ManyMapperTest { @Test public void test_insertStudent() { SqlSession session=null; session = MyBatisSqlSessionFactory.openSession();//使用封装之后的类 // 使用sqlsession获得映射接口的实现类对象,接口的引用指向实现类的对象 Many2ManyMapper mapper = session.getMapper(Many2ManyMapper.class); Student student=new Student(1,"Suwu150","男","计算机","21"); mapper.insertStudent(student); session.commit(); System.out.println("执行完毕"); } @Test public void test_insertCourse() { SqlSession session=null; session = MyBatisSqlSessionFactory.openSession();//使用封装之后的类 // 使用sqlsession获得映射接口的实现类对象,接口的引用指向实现类的对象 Many2ManyMapper mapper = session.getMapper(Many2ManyMapper.class); mapper.insertCourse(new Course(1,"001","corejava")); mapper.insertCourse(new Course(2,"002","oracle")); session.commit(); System.out.println("执行完毕"); } @Test public void test_selectStudentById() { SqlSession session=null; session = MyBatisSqlSessionFactory.openSession();//使用封装之后的类 // 使用sqlsession获得映射接口的实现类对象,接口的引用指向实现类的对象 Many2ManyMapper mapper = session.getMapper(Many2ManyMapper.class); Student student = mapper.selectStudentById(2); System.out.println(student); System.out.println("执行完毕"); } @Test public void test_selectCourseById() { SqlSession session=null; session = MyBatisSqlSessionFactory.openSession();//使用封装之后的类 // 使用sqlsession获得映射接口的实现类对象,接口的引用指向实现类的对象 Many2ManyMapper mapper = session.getMapper(Many2ManyMapper.class); Course course = mapper.selectCourseById(2); System.out.println(course); System.out.println("执行完毕"); } @Test public void test_studentSelectCourse() { SqlSession session=null; session = MyBatisSqlSessionFactory.openSession();//使用封装之后的类 // 使用sqlsession获得映射接口的实现类对象,接口的引用指向实现类的对象 Many2ManyMapper mapper = session.getMapper(Many2ManyMapper.class); Student student=new Student(); Course course=new Course(); student.setId(2); course.setId(1); mapper.studentSelectCourse(5, student, course); session.commit(); } @Test public void test_getStudentByIdOnCondition() { SqlSession session=null; session = MyBatisSqlSessionFactory.openSession();//使用封装之后的类 // 使用sqlsession获得映射接口的实现类对象,接口的引用指向实现类的对象 Many2ManyMapper mapper = session.getMapper(Many2ManyMapper.class); List<Student> list = mapper.getStudentByIdOnCondition(3); System.out.println(list); } @Test public void test_getStudentByIdWithCourses() { SqlSession session=null; session = MyBatisSqlSessionFactory.openSession();//使用封装之后的类 // 使用sqlsession获得映射接口的实现类对象,接口的引用指向实现类的对象 Many2ManyMapper mapper = session.getMapper(Many2ManyMapper.class); Student student = mapper.getStudentByIdWithCourses(2); System.out.println(student); }}注:这是从student这边出发所做的一些操作,从course一边开始操作是一样的,因为俩者的关系是多对多(对称的).
同时不论是一对一还是一对多还是多对多,都不能在mybatis中进行级联保存、更新、删除,我们需要使用sql语句控制每一步操作