MyBatis保姆级理解与使用学习关联关系
1. 关联关系
1.1 关联关系概念说明
表与表之间的关系 : 1 对 1 1对多 多对多关系 ,通过主外键来实现。
外键在多的一方。比如员工和部门: 1个员工对应一个部门,一个部门可以有多个员工
要将表与表之间的关系:映射称为 类与类之间的关系(准确的说应该是 对象和对象之间的关系 )
一对一
夫妻关系,人和身份证号的关系
一对多
部门 员工
多对多:一般都是引入第三张表来解决。
学生 课程 成绩
老师 学生
2. 创建模型
create database mybatisdb03 default charset = utf8;
use mybatisdb03;
drop table sys_emp; drop table sys_dept;
create table sys_dept( dept_id bigint auto_increment, dept_name varchar(20), dept_createdate varchar(20), dept_tel varchar(20) unique, dept_status enum('y','n') default 'y', primary key(dept_id) );
INSERT INTO `sys_dept` VALUES (null, '学术部', '2011-1-1', '0710-312345',default); INSERT INTO `sys_dept` VALUES (null, '市场部', '2012-3-1', '0710-394566',default); INSERT INTO `sys_dept` VALUES (null, '教质部', '2012-1-1', '0710-335667',default); INSERT INTO `sys_dept` VALUES (null, '就业部', '2015-2-3', '0710-393568',default);
create table sys_emp( emp_id bigint auto_increment, emp_name varchar(20), emp_pwd varchar(20), emp_gender enum('m','f'), emp_salary double(10,5), emp_status enum('y','n') default 'y', dept_id bigint comment '外键', primary key(emp_id) );
INSERT INTO `sys_emp` VALUES (null, '范冰冰', 'fbb', 'f', 100.5,default,1); INSERT INTO `sys_emp` VALUES (null, '李冰冰', 'lbb', 'f', 300,default,2); INSERT INTO `sys_emp` VALUES (null, '张彬彬', 'zbb', 'm', 599,default,3); INSERT INTO `sys_emp` VALUES (null, '万茜', 'wq', 'm', 4000,default,1); INSERT INTO `sys_emp` VALUES (null, '李若彤', 'lrt', 'm', 5000.8,default,1);
select * from `sys_dept`; select * from `sys_emp`; |
现在一般外面做项目,如果数据量过大,只建立外键,但是不建立外键约束。
package com.hy.bean;
import java.util.Date; import java.util.List;
import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter;
@Setter @Getter @NoArgsConstructor @AllArgsConstructor public class Dept { private Long deptId; private String deptName; private Date deptCreatedate; private String deptTel; private String deptStatus;
//体现对多的关系 private List<Emp> empList;
//去ID,去关系的 public Dept(String deptName, Date deptCreatedate, String deptTel, String deptStatus) { super(); this.deptName = deptName; this.deptCreatedate = deptCreatedate; this.deptTel = deptTel; this.deptStatus = deptStatus; }
@Override public String toString() { return "Dept [deptId=" + deptId + ", deptName=" + deptName + ", deptCreatedate=" + deptCreatedate + ", deptTel=" + deptTel + ", deptStatus=" + deptStatus + ", empList=" + empList + "]"; } }
|
package com.hy.bean;
import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter;
@Setter @Getter @NoArgsConstructor @AllArgsConstructor public class Emp { private Long empId; private String empName; private String empPwd; private String empGender; private Double empSalary; private String empStatus; private Long deptId;
// 体现对一的关系 private Dept dept;
public Emp(String empName, String empPwd, String empGender, Double empSalary, String empStatus, Long deptId) { super(); this.empName = empName; this.empPwd = empPwd; this.empGender = empGender; this.empSalary = empSalary; this.empStatus = empStatus; this.deptId = deptId; }
@Override public String toString() { return "Emp [empId=" + empId + ", empName=" + empName + ", empPwd=" + empPwd + ", empGender=" + empGender + ", empSalary=" + empSalary + ", empStatus=" + empStatus + ", deptId=" + deptId + ", dept=" + dept + "]"; } } |
2. 演示[一对多]关系,联接查询
关联关系的方法,主要体现在Java实体类的对象中:
单向:双方中只有一方能够访问到对方
Dept类的对象中empList属性为null
Emp 类的对象中的dept的属性为null
双向:双方都可以访问到对方
Dept类的对象中empList属性不为null,并且包含了该部门的员工对象
Emp 类的对象中的dept的属性为不为null,指向了该员工对象的部门对象
3.1 对一的关系(单向)
我们希望查出Emp类的对象的时候,将其关联的Dept信息也查询出来,并且填充进去。
3.1.1 创建EmpMapper接口
package com.hy.mapper;
import org.apache.ibatis.annotations.Param;
import com.hy.bean.Emp;
public interface EmpMapper { abstract public Emp selectByIdWithDept(@Param("empId") long empId); }
|
3.1.2 创建EmpMapper.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">
<mapper namespace="com.hy.mapper.EmpMapper"> <resultMap id="empResultMap" type="com.hy.bean.Emp" > <!-- 映射Emp本身的属性 --> <!-- property属性:给Emp对象中的哪一个属性设置数据 --> <id column="emp_id" property="empId"/> <result column="emp_name" property="empName"/> <result column="emp_pwd" property="empPwd"/> <result column="emp_gender" property="empGender"/> <result column="emp_salary" property="empSalary"/> <result column="emp_status" property="empStatus"/> <result column="dept_id" property="deptId"/>
<!-- association标签,映射对一关联关系:给Emp的dept属性填充数据 --> <!-- javaType属性:property属性的类型,可省略 --> <association property="dept" javaType="com.hy.bean.Dept"> <id column="dept_id" property="deptId"/> <result column="dept_name" property="deptName"/> <result column="dept_createdate" property="deptCreatedate"/> <result column="dept_tel" property="deptTel"/> <result column="dept_status" property="deptStatus"/> </association> </resultMap>
<!-- 注意,这里不能用resultType,否则无法将查询出来的sys_dept表中的字段映射到,映射Emp类的对象中--> <select id="selectByIdWithDept" resultMap="empResultMap"> select * from sys_emp emp inner join sys_dept dept on emp.dept_id = dept.dept_id where emp.emp_id = #{empId} </select> </mapper>
|
3.1.3 测试类:
@Test public void testSelectByIdWithDept() throws IOException { // 5. 通过sqlSession对象通过反射机制,直接生成一个EmpMapper接口的匿名类的对象 EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
// 6. 执行语句,打印结果 Emp emp = empMapper.selectByIdWithDept(1L); System.out.println(emp); System.out.println(emp.getDept()); } |
一般不会这么设计在1的一端,比如部门,记住所有的员工,但是在多的一端不能记住1的一端。
让姚明 记住 全国人民简单 还是 让全国人民记住 姚明简单。
记住,在多的一端维护1的一端关系,比较简单。
1 *
比如Dept--------------Emp ,Emp这边是多的一端,让Emp去维护 这个对1的关系。
3.2 对多的关系(单向)
在“对多”的关联关系中,有很多配置,但是关键的是collection 和 ofType
3.2.1 创建DeptMapper接口
package com.hy.mapper;
import org.apache.ibatis.annotations.Param;
import com.hy.bean.Dept;
public interface DeptMapper { abstract public Dept selectByIdWithEmp(@Param("deptId") long deptId); } |
3.2.2 创建DeptMapper.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">
<mapper namespace="com.hy.mapper.DeptMapper"> <resultMap id="deptResultMap" type="com.hy.bean.Dept"> <id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/> <result column="dept_createdate" property="deptCreatedate"/> <result column="dept_tel" property="deptTel"/> <result column="dept_status" property="deptStatus"/>
<collection property="empList" ofType="com.hy.bean.Emp"> <id column="emp_id" property="empId"/> <result column="emp_name" property="empName"/> <result column="emp_pwd" property="empPwd"/> <result column="emp_gender" property="empGender"/> <result column="emp_salary" property="empSalary"/> <result column="emp_status" property="empStatus"/> <result column="dept_id" property="deptId"/> </collection> </resultMap>
<select id="selectByIdWithEmp" resultMap="deptResultMap"> select * from sys_emp emp left join sys_dept dept on emp.dept_id = dept.dept_id where dept.dept_id = #{deptId} </select> </mapper> |
3.2.3 测试类
package com.hy.mybatis.test;
import java.io.IOException;
import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test;
import com.hy.bean.Dept; import com.hy.mapper.DeptMapper;
public class TestDeptMapperPro { private SqlSession sqlSession;
// junit会在每一个@Test方法前, 执行@Before方法 @Before public void init() throws IOException { //1,2,3,4 sqlSession = new SqlSessionFactoryBuilder().build( Resources.getResourceAsStream("mybatis-config.xml") ) .openSession();
}
@Test public void testSelectByIdWithEmp() throws IOException { // 5. 通过sqlSession对象通过反射机制,直接生成一个EmpMapper接口的匿名类的对象 DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
// 6. 执行语句,打印结果 Dept dept = deptMapper.selectByIdWithEmp(1); System.out.println(dept); System.out.println(dept.getEmpList()); }
// junit会在每一个@Test方法后, 执行@After方法 @After public void clear() throws IOException { // 7. 提交事务 sqlSession.commit();
// 8. 关闭sqlSession sqlSession.close(); } } |
Dept [deptId=1, deptName=学术部, deptCreatedate=Sun Sep 29 00:00:00 CST 110, deptTel=0710-312345, deptStatus=y,
empList=[Emp [empId=1, empName=范冰冰, empPwd=fbb, empGender=f, empSalary=100.5, empStatus=y, deptId=1, dept=null], Emp [empId=4, empName=万茜, empPwd=wq, empGender=m, empSalary=4000.0, empStatus=y, deptId=1, dept=null], Emp [empId=5, empName=李若彤, empPwd=lrt, empGender=m, empSalary=5000.8, empStatus=y, deptId=1, dept=null]]]
[Emp [empId=1, empName=范冰冰, empPwd=fbb, empGender=f, empSalary=100.5, empStatus=y, deptId=1, dept=null], Emp [empId=4, empName=万茜, empPwd=wq, empGender=m, empSalary=4000.0, empStatus=y, deptId=1, dept=null], Emp [empId=5, empName=李若彤, empPwd=lrt, empGender=m, empSalary=5000.8, empStatus=y, deptId=1, dept=null]]
3.3 一对多的关系(双向)
3.3.1 DeptMapper接口中的方法
package com.hy.mapper;
import org.apache.ibatis.annotations.Param;
import com.hy.bean.Dept;
public interface DeptMapper { abstract public Dept selectByIdWithEmp(@Param("deptId") long deptId);
abstract public Dept selectByIdWithEmpBoth(@Param("deptId") long deptId); } |
3.3.2 DeptMapper.xml
<!-- 分割线,双线连接查询 --> <resultMap id="deptWithEmpListResultMapBoth" type="com.hy.bean.Dept"> <id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/> <result column="dept_createdate" property="deptCreatedate"/> <result column="dept_tel" property="deptTel"/> <result column="dept_status" property="deptStatus"/>
<collection property="empList" ofType="com.hy.bean.Emp" resultMap="com.hy.mapper.EmpMapper.empResultMapBoth"/> </resultMap>
<select id="selectByIdWithEmpBoth" resultMap="deptWithEmpListResultMapBoth"> select * from sys_dept dept left join sys_emp emp on dept.dept_id = emp.dept_id where dept.dept_id = #{deptId} </select> |
3.3.3 EmpMapper.xml
<!-- 双向关联 --> <resultMap id="empResultMapBoth" type="com.hy.bean.Emp" > <!-- 映射Emp本身的属性 --> <!-- property属性:给Emp对象中的哪一个属性设置数据 --> <id column="emp_id" property="empId"/> <result column="emp_name" property="empName"/> <result column="emp_pwd" property="empPwd"/> <result column="emp_gender" property="empGender"/> <result column="emp_salary" property="empSalary"/> <result column="emp_status" property="empStatus"/> <result column="dept_id" property="deptId"/>
<!-- association标签,映射对一关联关系:给Emp的dept属性填充数据 --> <!-- javaType属性:property属性的类型,可省略 --> <association property="dept" javaType="com.hy.bean.Dept" resultMap="com.hy.mapper.DeptMapper.deptWithEmpListResultMapBoth" /> </resultMap> |
3.3.4 测试类:
@Test public void selectByIdWithEmpBoth() throws IOException { // 5. 通过sqlSession对象通过反射机制,直接生成一个EmpMapper接口的匿名类的对象 DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
// 6. 执行语句,打印结果 Dept dept = deptMapper.selectByIdWithEmpBoth(1L); System.out.println(dept); System.out.println(dept.getEmpList()); } |
4. 演示[1对多],分步查询
上面不论是从Dept查Emp,还是从Emp查Dept,都是通过一条连接查询的SQL语句来完成的,将dept和emp的信息一起查出来了,然后通过mybatis组装起来。此时就有一个问题,查询出来的关联对象不一定会被用到。查询dept的时候,不管emp用不用,都会将emp查询出来,并封装起来。此时如果查询出来,但是暂时又用不上,然后你又装配起来了,此时就会造成内存你的浪费,但是如果你不查出来,但是万一又用了,此时又没有。
此时,我希望既能维持关联关系,又希望在用的时候才将其查询出来,不用的时候,不查。这就叫延迟加载—也叫懒加载。就是到使用的时候才用将其查询出来。使用场景:
所以分布查询是懒加载的基础。
4.1 实现
为了实现懒加载—延迟加载,对sys_dept和sys_emp的查询必须分开,分成两步来做,才能够实现。为此,我们需要单独查询sys_dept 和 sys_emp的SQL语句。
4.2 分布对1的关系:
4.2.1 bean的写法
package com.hy.bean;
import java.util.Date; import java.util.List;
import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter;
@Setter @Getter @NoArgsConstructor @AllArgsConstructor public class Dept { private Long deptId; private String deptName; private Date deptCreatedate; private String deptTel; private String deptStatus;
//体现对多的关系 private List<Emp> empList;
//去ID,去关系的 public Dept(String deptName, Date deptCreatedate, String deptTel, String deptStatus) { super(); this.deptName = deptName; this.deptCreatedate = deptCreatedate; this.deptTel = deptTel; this.deptStatus = deptStatus; }
@Override public String toString() { return "Dept [deptId=" + deptId + ", deptName=" + deptName + ", deptCreatedate=" + deptCreatedate + ", deptTel=" + deptTel + ", deptStatus=" + deptStatus;// + ", empList=" + empList + "]"; } }
|
package com.hy.bean;
import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter;
@Setter @Getter @NoArgsConstructor @AllArgsConstructor public class Emp { private Long empId; private String empName; private String empPwd; private String empGender; private Double empSalary; private String empStatus; private Long deptId;
// 体现对一的关系 private Dept dept;
//去ID的,去关系 public Emp(String empName, String empPwd, String empGender, Double empSalary, String empStatus, Long deptId) { super(); this.empName = empName; this.empPwd = empPwd; this.empGender = empGender; this.empSalary = empSalary; this.empStatus = empStatus; this.deptId = deptId; }
@Override public String toString() { return "Emp [empId=" + empId + ", empName=" + empName + ", empPwd=" + empPwd + ", empGender=" + empGender + ", empSalary=" + empSalary + ", empStatus=" + empStatus + ", deptId=" + deptId ; // "+ , dept=" + dept + "]"; } } |
4.2.2 mapper接口的写法
package com.hy.mapper;
import org.apache.ibatis.annotations.Param;
import com.hy.bean.Dept;
public interface DeptMapper { abstract public Dept selectByIdWithTwoStep(@Param("deptId") long deptId); } |
package com.hy.mapper;
import org.apache.ibatis.annotations.Param;
import com.hy.bean.Emp;
public interface EmpMapper { abstract public Emp selectByIdWithDeptTwoStep(@Param("empId") long empId); } |
4.2.3 映射的文件的写法
<?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.hy.mapper.DeptMapper"> <!-- 定位到当前SQL语句的方式:com.hy.mapper.DeptMapper.selectById --> <!-- 这条语句仅仅是根据id查询部门 --> <select id="selectById" resultType="com.hy.bean.Dept"> select dept_id,dept_name,dept_createdate,dept_tel,dept_status from sys_dept where dept_id = #{deptId} </select>
<!-- 两步 --> <resultMap type="com.hy.bean.Dept" id="deptResultMapBoth"> <id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/> <result column="dept_createdate" property="deptCreatedate"/> <result column="dept_tel" property="deptTel"/> <result column="dept_status" property="deptStatus"/>
<collection property="empList" column="dept_id" ofType="com.hy.bean.Emp" select="com.hy.mapper.EmpMapper.selectByFid"/>
</resultMap> <select id="selectByIdWithTwoStep" resultMap="deptResultMapBoth"> select dept_id,dept_name,dept_createdate,dept_tel,dept_status from sys_dept where dept_id = #{deptId} </select> </mapper> |
<?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.hy.mapper.EmpMapper"> <resultMap id="empResultMap" type="com.hy.bean.Emp" > <!-- 映射Emp本身的属性 --> <!-- property属性:给Emp对象中的哪一个属性设置数据 --> <id column="emp_id" property="empId"/> <result column="emp_name" property="empName"/> <result column="emp_pwd" property="empPwd"/> <result column="emp_gender" property="empGender"/> <result column="emp_salary" property="empSalary"/> <result column="emp_status" property="empStatus"/> <result column="dept_id" property="deptId"/>
<!-- association标签,映射对一关联关系:给Emp的dept属性填充数据 --> <!-- select属性:定位到另外一条专门查询dept的SQL语句--> <!-- column属性:指定用来给查询 sys_dept 的SQL语句传参的字段--> <association property="dept" column="dept_id" select="com.hy.mapper.DeptMapper.selectById" /> </resultMap>
<select id="selectByIdWithDeptTwoStep" resultMap="empResultMap"> select * from sys_emp where emp_id = #{empId} </select>
<select id="selectByFid" resultType="com.hy.bean.Emp"> select * from sys_emp where dept_id = #{deptId} </select> </mapper> |
4.2.4 mybaits-config.xml全局配置文件中注意
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> |
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="jdbc.properties"/>
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
<environments default="development"> <!-- environment表示配置Mybaits的一个具体的环境 --> <environment id="development"> <!-- Mybaits的内置的事务管理器 --> <transactionManager type="JDBC" /> <!-- 配置数据源,这里使用的是Mybaits内置的数据源--> <dataSource type="POOLED"> <!-- 建立数据库连接的具体信息 --> <property name="driver" value="${mybatis03.dev.driver}" /> <property name="url" value="${mybatis03.dev.url}" /> <property name="username" value="${mybatis03.dev.username}" /> <property name="password" value="${mybatis03.dev.password}" /> </dataSource> </environment> </environments> <!-- 设置映射文件的路径,还没有写 --> <mappers> <mapper resource="mappers/EmpMapper.xml" /> <mapper resource="mappers/DeptMapper.xml" /> </mappers> </configuration> |
4.2.5 测试类
package com.hy.mybatis.test;
import java.io.IOException;
import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test;
import com.hy.bean.Dept; import com.hy.bean.Emp; import com.hy.mapper.DeptMapper;
public class TestDeptMapperPro { private SqlSession sqlSession;
// junit会在每一个@Test方法前, 执行@Before方法 @Before public void init() throws IOException { //1,2,3,4 sqlSession = new SqlSessionFactoryBuilder().build( Resources.getResourceAsStream("mybatis-config.xml") ) .openSession();
}
@Test public void testSelectByIdWithTwoStep() throws IOException { // 5. 通过sqlSession对象通过反射机制,直接生成一个EmpMapper接口的匿名类的对象 DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
// 6. 执行语句,打印结果 Dept dept = deptMapper.selectByIdWithTwoStep(1L); System.out.println(dept); System.out.println(dept.getEmpList()); }
// junit会在每一个@Test方法后, 执行@After方法 @After public void clear() throws IOException { // 7. 提交事务 sqlSession.commit();
// 8. 关闭sqlSession sqlSession.close(); } } |
package com.hy.mybatis.test;
import java.io.IOException;
import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test;
import com.hy.bean.Emp; import com.hy.mapper.EmpMapper;
public class TestEmpMapperPro { private SqlSession sqlSession;
// junit会在每一个@Test方法前, 执行@Before方法 @Before public void init() throws IOException { //1,2,3,4 sqlSession = new SqlSessionFactoryBuilder().build( Resources.getResourceAsStream("mybatis-config.xml") ) .openSession();
}
@Test public void testSelectByIdWithDept() throws IOException { // 5. 通过sqlSession对象通过反射机制,直接生成一个EmpMapper接口的匿名类的对象 EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
// 6. 执行语句,打印结果 Emp emp = empMapper.selectByIdWithDeptTwoStep(1); System.out.println(emp); System.out.println(emp.getDept()); }
// junit会在每一个@Test方法后, 执行@After方法 @After public void clear() throws IOException { // 7. 提交事务 sqlSession.commit();
// 8. 关闭sqlSession sqlSession.close(); } } |
4.3 图解:
4.4 懒查询
配置fetchType=”lazy”
5. 演示多对多关系
5.1 建立模型
create database mybatisdb03 default charset = utf8;
use mybatisdb03;
create table sys_student( student_id bigint auto_increment, student_name varchar(20), student_gender enum('m','f'), primary key(student_id) );
INSERT INTO `sys_student` VALUES (null, '范冰冰', 'f'); INSERT INTO `sys_student` VALUES (null, '李冰冰', 'f'); INSERT INTO `sys_student` VALUES (null, '张彬彬', 'm'); INSERT INTO `sys_student` VALUES (null, '万茜', 'm'); INSERT INTO `sys_student` VALUES (null, '李若彤', 'm');
create table `sys_course`( course_id bigint auto_increment, course_name varchar(20) not null unique, primary key(sys_course) );
INSERT INTO `sys_course` VALUES (null, 'JSP'); INSERT INTO `sys_course` VALUES (null, 'mybatis'); INSERT INTO `sys_course` VALUES (null, 'SpringMVC');
create table `sys_student_course`( student_course_id bigint auto_increment, student_id bigint, course_id bigint, primary key(student_course_id) );
INSERT INTO `sys_student_course` VALUES (null, 1,1); INSERT INTO `sys_student_course` VALUES (null, 1,2); INSERT INTO `sys_student_course` VALUES (null, 2,1); INSERT INTO `sys_student_course` VALUES (null, 2,2); INSERT INTO `sys_student_course` VALUES (null, 3,1);
select * from sys_student stu left join sys_student_course sc on stu.student_id = sc.student_id left join sys_course course on course.course_id = sc.course_id |
5.2 bean
5.2.1 Course
package com.hy.bean;
import java.util.List;
import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter;
@Setter @Getter @NoArgsConstructor @AllArgsConstructor public class Course { private Long courseId; private String courseName;
//体现多对多关系 private List<Student> studentList;
@Override public String toString() { return "Course [courseId=" + courseId + ", courseName=" + courseName;// + ", studentList=" + studentList + "]"; } } |
5.2.2 Student
package com.hy.bean;
import java.util.List;
import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter;
@Setter @Getter @NoArgsConstructor @AllArgsConstructor public class Student { private Long studentId; private String studentName; private String studentGender;
//体现对多的关系 private List<Course> courseList;
@Override public String toString() { return "Student [studentId=" + studentId + ", studentName=" + studentName;// + ", studentGender=" + studentGender+ ", courseList=" + courseList + "]"; }
}
|
5.2.3 StudentMapper
package com.hy.mapper;
import java.util.List;
import com.hy.bean.Student;
public interface StudentMapper { abstract public List<Student> selectAll(); } |
5.2.4 StudentMapper.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">
<mapper namespace="com.hy.mapper.StudentMapper"> <resultMap id="studentResultMapBoth" type="com.hy.bean.Student" > <!-- 映射Emp本身的属性 --> <!-- property属性:给Emp对象中的哪一个属性设置数据 --> <id column="student_id" property="studentId"/> <result column="student_name" property="studentName"/> <result column="student_gender" property="studentGender"/>
<collection property="courseList" ofType="com.hy.bean.Course"> <id column="course_id" property="courseId"/> <result column="course_name" property="courseName"/> </collection> </resultMap>
<select id="selectAll" resultMap="studentResultMapBoth"> select * from sys_student stu left join sys_student_course sc on stu.student_id = sc.student_id left join sys_course course on course.course_id = sc.course_id </select> </mapper>
|
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!