MyBatis学习之多表操作
1.1 多表模型介绍
我们之前学习的都是基于单表操作的,而实际开发中,随着业务难度的加深,肯定需要多表操作的。
- 多表模型分类 一对一:在任意一方建立外键,关联对方的主键。
- 一对多:在多的一方建立外键,关联一的一方的主键。
- 多对多:借助中间表,中间表至少两个字段,分别关联两张表的主键。
1.2 多表模型一对一操作
-
一对一模型: 人和身份证,一个人只有一个身份证
-
代码实现
-
步骤一: sql语句准备及entity对象
CREATE TABLE person( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), age INT ); INSERT INTO person VALUES (NULL,'张三',23); INSERT INTO person VALUES (NULL,'李四',24); INSERT INTO person VALUES (NULL,'王五',25); CREATE TABLE card( id INT PRIMARY KEY AUTO_INCREMENT, number VARCHAR(30), pid INT, CONSTRAINT cp_fk FOREIGN KEY (pid) REFERENCES person(id) ); INSERT INTO card VALUES (NULL,'12345',1); INSERT INTO card VALUES (NULL,'23456',2); INSERT INTO card VALUES (NULL,'34567',3);
-
身份证对象:
package com.boxuegu.mybatisdemo.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
*
* @author 花海
* @since 2024-03-10
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class Card implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String number;
private Integer pid;
private Person p;
}
人对象:
package com.boxuegu.mybatisdemo.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @author 花海
* @since 2024-03-10
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private Integer age;
}
CardMapper接口:
package com.boxuegu.mybatisdemo.mapper;
import com.boxuegu.mybatisdemo.entity.Card;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author 花海
* @since 2024-03-10
*/
@Mapper
public interface CardMapper {
/**
* 查询所有的身份证,并展示关联的人员信息
* @return
*/
List<Card> selectAll();
}
- 步骤二:CardMapper接口配置文件
<?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.boxuegu.mybatisdemo.mapper.CardMapper">
<resultMap id="oneToOne" type="com.boxuegu.mybatisdemo.entity.Card">
<id column="cid" property="id"/>
<result column="number" property="number"/>
<!--
association:配置被包含对象的映射关系
property:被包含对象的变量名
javaType:被包含对象的数据类型
-->
<association property="p" javaType="com.boxuegu.mybatisdemo.entity.Person">
<id column="pid" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
</association>
</resultMap>
<select id="selectAll" resultMap="oneToOne">
SELECT c.id cid, number, pid, NAME, age
FROM card c,
person p
WHERE c.pid = p.id
</select>
</mapper>
- 步骤三:测试类
package com.boxuegu.mybatisdemo;
import com.boxuegu.mybatisdemo.entity.Card;
import com.boxuegu.mybatisdemo.mapper.CardMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class MybatisDemoApplicationTests {
@Autowired
private CardMapper cardMapper;
@Test
public void selectAllCards(){
List<Card> cards = cardMapper.selectAll();
for (Card card : cards) {
System.out.println(card);
}
}
}
测试结果:
3.一对一配置总结:
<resultMap>:配置字段和对象属性的映射关系标签。
id 属性:唯一标识
type 属性:实体对象类型
<id>:配置主键映射关系标签。
<result>:配置非主键映射关系标签。
column 属性:表中字段名称
property 属性: 实体对象变量名称
<association>:配置被包含对象的映射关系标签。
property 属性:被包含对象的变量名
javaType 属性:被包含对象的数据类型
1.3 多表模型一对多操作
-
一对多模型: 一对多模型:班级和学生,一个班级可以有多个学生。
-
代码实现
-
步骤一: sql语句准备及entity对象准备
CREATE TABLE classes( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20) ); INSERT INTO classes VALUES (NULL,'黑马一班'); INSERT INTO classes VALUES (NULL,'黑马二班'); CREATE TABLE student( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(30), age INT, cid INT, CONSTRAINT cs_fk FOREIGN KEY (cid) REFERENCES classes(id) ); INSERT INTO student VALUES (NULL,'张三',23,1); INSERT INTO student VALUES (NULL,'李四',24,1); INSERT INTO student VALUES (NULL,'王五',25,2); INSERT INTO student VALUES (NULL,'赵六',26,2);
-
班级对象:
package com.boxuegu.mybatisdemo.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
*
* </p>
*
* @author 花海
* @since 2024-03-10
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class Classes implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private List<Student> students = new ArrayList<>();
}
学生对象:
package com.boxuegu.mybatisdemo.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @author 花海
* @since 2024-03-10
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private Integer age;
private Integer cid;
}
ClassesMapper接口:
package com.boxuegu.mybatisdemo.mapper;
import com.boxuegu.mybatisdemo.entity.Classes;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author 花海
* @since 2024-03-10
*/
@Mapper
public interface ClassesMapper {
public List<Classes> selectAll();
}
-
步骤二:ClassesMapper接口配置文件
<?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.boxuegu.mybatisdemo.mapper.ClassesMapper"> <resultMap id="oneToMany" type="com.boxuegu.mybatisdemo.entity.Classes"> <id column="cid" property="id"/> <result column="cname" property="name"/> <!-- collection:配置被包含的集合对象映射关系 property:被包含对象的变量名 ofType:被包含对象的实际数据类型 --> <collection property="students" ofType="com.boxuegu.mybatisdemo.entity.Student"> <id column="sid" property="id"/> <result column="sname" property="name"/> <result column="sage" property="age"/> </collection> </resultMap> <select id="selectAll" resultMap="oneToMany"> SELECT c.id cid, c.name cname, s.id sid, s.name sname, s.age sage FROM classes c, student s WHERE c.id = s.cid </select> </mapper>
-
步骤三:测试类
@Autowired
private ClassesMapper classesMapper;
@Test
public void selectAllClasses(){
List<Classes> classesList = classesMapper.selectAll();
for (Classes classes : classesList) {
System.out.println(classes);
}
}
测试结果:
3.一对多配置文件总结:
<resultMap>:配置字段和对象属性的映射关系标签。
id 属性:唯一标识
type 属性:实体对象类型
<id>:配置主键映射关系标签。
<result>:配置非主键映射关系标签。
column 属性:表中字段名称
property 属性: 实体对象变量名称
<collection>:配置被包含集合对象的映射关系标签。
property 属性:被包含集合对象的变量名
ofType 属性:集合中保存的对象数据类型
1.4 多表模型多对多操作
-
多对多模型:学生和课程,一个学生可以选择多门课程、一个课程也可以被多个学生所选择。
-
代码实现
-
步骤一: sql语句准备及entity对象准备
CREATE TABLE course( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20) ); INSERT INTO course VALUES (NULL,'语文'); INSERT INTO course VALUES (NULL,'数学'); CREATE TABLE stu_cr( id INT PRIMARY KEY AUTO_INCREMENT, sid INT, cid INT, CONSTRAINT sc_fk1 FOREIGN KEY (sid) REFERENCES student(id), CONSTRAINT sc_fk2 FOREIGN KEY (cid) REFERENCES course(id) ); INSERT INTO stu_cr VALUES (NULL,1,1); INSERT INTO stu_cr VALUES (NULL,1,2); INSERT INTO stu_cr VALUES (NULL,2,1); INSERT INTO stu_cr VALUES (NULL,2,2);
-
Student对象:
package com.boxuegu.mybatisdemo.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
*
* </p>
*
* @author 花海
* @since 2024-03-10
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private Integer age;
private Integer cid;
private List<Course> courses = new ArrayList<>();
}
Course对象:
package com.boxuegu.mybatisdemo.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @author 花海
* @since 2024-03-10
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class Course implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
}
StudentMapper对象:
package com.boxuegu.mybatisdemo.mapper;
import com.boxuegu.mybatisdemo.entity.Student;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author 花海
* @since 2024-03-10
*/
@Mapper
public interface StudentMapper{
List<Student> selectAll();
}
-
步骤二:StudentMapper对象配置文件
<?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.boxuegu.mybatisdemo.mapper.StudentMapper"> <resultMap id="manyToMany" type="com.boxuegu.mybatisdemo.entity.Student"> <id column="sid" property="id"/> <result column="sname" property="name"/> <result column="sage" property="age"/> <collection property="courses" ofType="com.boxuegu.mybatisdemo.entity.Course"> <id column="cid" property="id"/> <result column="cname" property="name"/> </collection> </resultMap> <select id="selectAll" resultMap="manyToMany"> SELECT sc.sid,s.name sname,s.age sage,sc.cid,c.name cname FROM student s,course c,stu_cr sc WHERE sc.sid=s.id AND sc.cid=c.id </select> </mapper>
-
步骤三:测试类
@Autowired private StudentMapper studentMapper; @Test public void selectAllStudents(){ List<Student> studentList = studentMapper.selectAll(); for (Student student : studentList) { System.out.println(student); } }
测试结果:
3.多对多配置文件总结:
<resultMap>:配置字段和对象属性的映射关系标签。
id 属性:唯一标识
type 属性:实体对象类型
<id>:配置主键映射关系标签。
<result>:配置非主键映射关系标签。
column 属性:表中字段名称
property 属性: 实体对象变量名称
<collection>:配置被包含集合对象的映射关系标签。
property 属性:被包含集合对象的变量名
ofType 属性:集合中保存的对象数据类型
1.5 多表模型操作总结
<resultMap>:配置字段和对象属性的映射关系标签。
id 属性:唯一标识
type 属性:实体对象类型
<id>:配置主键映射关系标签。
<result>:配置非主键映射关系标签。
column 属性:表中字段名称
property 属性: 实体对象变量名称
<association>:配置被包含对象的映射关系标签。
property 属性:被包含对象的变量名
javaType 属性:被包含对象的数据类型
<collection>:配置被包含集合对象的映射关系标签。
property 属性:被包含集合对象的变量名
ofType 属性:集合中保存的对象数据类型