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;
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
+ "]";
}
}
Student类实现:
package com.mybatis.pojo;
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 + "]";
}
}
在设置完上面的操作之后,我们进行配置mybatis-config.xml文件注册基本信息
<?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;
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);
}
配置Many2ManyMapper.xml:
<?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语句控制每一步操作