接上篇【MyBatis】学习纪要一:SpringBoot集成MyBatis完成增删查改,本节我们来研究一下常用的关联关系:一对一
、一对多
、多对一
、多对多
。
看了我的第一篇,大家可能有一个疑问,我提供的代码(github上)有采用注解的方式,多简洁啊,为什么在这个学习系列要用 XML
的方式啊,这种写起来好麻烦啊。
其实,我也不喜欢这种方式,这也是我最初学习Hibernate(JPA),不学习MyBatis的原因,相反,我还觉得它非常难学。这个问题的在开篇之处就告诉大家了,采用 XML
的方式,我们可以自己写 SQL
,后期也好优化。大抵就这两点。其他的话,可能有的人有,有的人没有。
以前在学 SQL
的时候,关联关系,我们会以外键的方式存取,因此,这四种关系,可以用一个关键词解决—— association
。
没错就是它,只要学了它,基本就够用了,但是MyBatis还为我们提供了一个关键词——collection
。
所以,下面我们就来学习这两个关键词。
association假设一个班级一个班主任,一个老师也只能是一个班的班主任,这样班级和班主任之前就是一一对应的关系的,相当于一对一
。
Teacher
package com.fengwenyi.demo1.entity;
/**
* @author Wenyi Feng
*/
public class Teacher {
private Long id;
private String name;
// getter and setter
}
Cls
package com.fengwenyi.demo1.entity;
/**
* @author Wenyi Feng
*/
public class Cls {
private Long id;
private String name;
private Teacher teacher;
// getter and setter
}
建数据表
DROP TABLE IF EXISTS `cls`;
CREATE TABLE `cls` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`teacher_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk` (`teacher_id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`cls_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk` (`cls_id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
ClsDao
package com.fengwenyi.demo1.dao;
import com.fengwenyi.demo1.entity.Cls;
import org.apache.ibatis.annotations.Mapper;
/**
* @author Wenyi Feng
*/
@Mapper
public interface ClsDao {
Cls findByTeacherId (Long teacherId);
}
ClsMapper
<?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" >
<mapper namespace="com.fengwenyi.demo1.dao.ClsDao" >
<resultMap id="BaseResultMap" type="com.fengwenyi.demo1.entity.Cls" >
<id column="cId" property="id" jdbcType="BIGINT" />
<result column="cName" property="name" jdbcType="VARCHAR" />
<association property="teacher" javaType="com.fengwenyi.demo1.entity.Teacher">
<id column="tId" property="id" jdbcType="BIGINT" />
<result column="tName" property="name" jdbcType="VARCHAR" />
</association>
</resultMap>
<select id="findByTeacherId" resultMap="BaseResultMap" parameterType="java.lang.Long" >
SELECT
c.id as cId,
c.name as cName,
t.id as tId,
t.name as tName
FROM
cls c, teacher t
WHERE
c.teacher_id = t.id
AND
c.teacher_id = #{teacherId}
</select>
</mapper>
ClsService
package com.fengwenyi.demo1.service;
import com.fengwenyi.demo1.dao.ClsDao;
import com.fengwenyi.demo1.entity.Cls;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author Wenyi Feng
*/
@Service
public class ClsService {
@Autowired
private ClsDao clsDao;
public Cls findByTeacherId (Long teacherId) {
return clsDao.findByTeacherId(teacherId);
}
}
测试一下:
package com.fengwenyi.demo1;
import com.fengwenyi.demo1.entity.Cls;
import com.fengwenyi.demo1.service.ClsService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author Wenyi Feng
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestOne2One {
@Autowired
private ClsService clsService;
@Test
public void test1 () {
Cls cls = clsService.findByTeacherId(1L);
System.out.println(cls.toString());
}
}
结果:
数据库只有一条数据,没问题。
collection如果把上面那个看懂的话,这个不就简单,因此,我只给出关键代码。
这次我们以班级和学生为例。
Cls
package com.fengwenyi.demo1.entity;
import java.util.List;
/**
* @author Wenyi Feng
*/
public class Cls {
private Long id;
private String name;
private List<Student> students;
private Teacher teacher;
// getter and setter
}
Student
package com.fengwenyi.demo1.entity;
/**
* @author Wenyi Feng
*/
public class Student {
private Long id;
private String name;
private Cls cls;
// getter and setter
}
student.sql
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`cls_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk` (`cls_id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4;
ClsMapper
<?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" >
<mapper namespace="com.fengwenyi.demo1.dao.ClsDao" >
<resultMap id="BaseResultMap" type="com.fengwenyi.demo1.entity.Cls" >
<id column="cId" property="id" jdbcType="BIGINT" />
<result column="cName" property="name" jdbcType="VARCHAR" />
<association property="teacher" javaType="com.fengwenyi.demo1.entity.Teacher">
<id column="tId" property="id" jdbcType="BIGINT" />
<result column="tName" property="name" jdbcType="VARCHAR" />
</association>
<collection property="students" ofType="com.fengwenyi.demo1.entity.Student">
<id column="sId" property="id" jdbcType="BIGINT" />
<result column="sName" property="name" jdbcType="VARCHAR" />
</collection>
</resultMap>
<select id="findByTeacherId" resultMap="BaseResultMap" parameterType="java.lang.Long" >
SELECT
c.id as cId,
c.name as cName,
t.id as tId,
t.name as tName
FROM
cls c, teacher t
WHERE
c.teacher_id = t.id
AND
c.teacher_id = #{teacherId}
</select>
<select id="findById" resultMap="BaseResultMap" parameterType="java.lang.Long" >
SELECT
c.id as cId,
c.name as cName,
t.id as tId,
t.name as tName,
s.id as sId,
s.name as sName
FROM
cls c, teacher t, student s
WHERE
c.teacher_id = t.id
AND
s.cls_id = c.id
AND
c.id = #{id}
</select>
</mapper>
测试代码:
@Test
public void test2 () {
Cls cls = clsService.findById(1L);
System.out.println(cls.toString());
List<Student> students = cls.getStudents();
for (Student student : students) {
System.out.println(student.toString());
}
}
测试结果: