这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战
概述数据库表关系
我们用的Mysql是一个关系型数据库,数据库中的表不都是独立存在的,数据库中的表存在着多种关系,一对一,一对多,多对多,拿出之前气门在SpringDataJpa里边的那张图。
通常在创建表的时候我们已经实现了这些关系
一对一关系:
- 可以共用主键,主键值是一样的
- 要不就是在一张表里有一个外键来确定他们的关系 一对多关系:在多的一方建立外键与一的一方的主键关联
多对多关系:通常是有一张中间表存储他们的主键来表示他们之间的。
Mybatis多表查询
数据准备
我们一共使用5张表来实现
Grade:班级表
role: 角色表
student:学生表
studentRole:学生角色表
stuInfo :学生详情表
一对一查询
一对一查询模型
学生和学生详情之间的关系,一个学生只有一个详情,这就是一对一的关系,之间共用主键,我们现在要实现查询学生信息查到他的详情信息
代码实现
实体类 Student
@Data
public class Student {
private Integer id;
private String studentName;
private Integer age;
private String address;
private Integer gradeId;
private StuInfo stuInfo;
}
实体类StuInfo
@Data
public class StuInfo {
private Integer infoid;
private String infoName;
}
实体类Grade
@Data
public class Grade {
private Integer gradeid;
private String gradeName;
private List<Student> student;
}
GradeMapper
<mapper namespace="com.study.mapper.GradeMapper">
<insert id="insertGrade" useGeneratedKeys="true" keyProperty="gradeid">
INSERT INTO mybatis_test.grade
( grade_name)
VALUES( #{gradeName});
</insert>
</mapper>
StudentMapper
<mapper namespace="com.study.mapper.StudentMapper">
<insert id="insert" useGeneratedKeys="true" keyProperty="id" >
INSERT INTO student
( studentname,age,address,gradeId)
VALUES( #{studentName}, #{age}, #{address},#{gradeId});
</insert>
</mapper>
StuInfoMapper
<mapper namespace="com.study.mapper.StuInfoMapper">
<insert id="insert">
INSERT INTO stuinfo
(infoid, info_name)
VALUES(#{infoid}, #{infoName});
</insert>
</mapper>
先给表里边塞点数据,把Gradeid也一块加上,添加班级的时候,添加学生,添加学生详情
@Test
public void test3(){
//获取sqlsession
SqlSession session = MybatisUtils.getSession();
GradeMapper mapper = session.getMapper(GradeMapper.class);
Grade grade = new Grade();
grade.setGradeName("一年级");
mapper.insertGrade(grade);
if (grade.getGradeid() != null){
StudentMapper mapper1 = session.getMapper(StudentMapper.class);
Student student = new Student();
student.setStudentName("张三");
student.setAge(22);
student.setGradeId(grade.getGradeid());
student.setAddress("科技城");
mapper1.insert(student);
if (student.getId() != null)
{
StuInfoMapper mapper2 = session.getMapper(StuInfoMapper.class);
StuInfo stuInfo1 = new StuInfo();
stuInfo1.setInfoName("银行卡");
stuInfo1.setInfoid(student.getId());
mapper2.insert(stuInfo1);
}
Student student1 = new Student();
student1.setStudentName("李四");
student1.setAge(22);
student1.setGradeId(grade.getGradeid());
student1.setAddress("科技城");
mapper1.insert(student1);
if (student1.getId() != null)
{
StuInfoMapper mapper2 = session.getMapper(StuInfoMapper.class);
StuInfo stuInfo1 = new StuInfo();
stuInfo1.setInfoName("暂住证");
stuInfo1.setInfoid(student1.getId());
mapper2.insert(stuInfo1);
}
}
session.commit();
session.close();
}
数据如下
现在开始写一对一查询,查询所有学生时查到学生详情信息,一对一使用三种方法实现
public interface StudentMapper {
void insert(Student student);
List<Student> findStudentAll();
List<Student> findStudentAll1();
List<Student> findStudentAll2();
}
第一种实现
sql语句实现功能
select * from student inner join stuinfo where student.id=stuinfo.infoid
我们想要是一个这样的结果
再给学生详情赋值时我们选择使用Student的stuInfo点相应的属性来赋值
<resultMap id="StudentInfo" type="com.study.pojo.Student">
<!--手动指定 表和属性之间的关系
column : 数据库字段名称
property :实体类属性名
-->
<id column="id" property="id"></id>
<result column="address" property="address"></result>
<result column="age" property="age"></result>
<result column="studentName" property="studentName"></result>
<result column="infoid" property="stuInfo.infoid"></result>
<result column="info_name" property="stuInfo.infoName"></result>
</resultMap>
<select id="findStudentAll" resultMap="StudentInfo">
select * from student inner join stuinfo where student.id=stuinfo.infoid
</select>
测试类(第二三种放发实体类同)
@Test
public void test2(){
//获取sqlsession
SqlSession session = MybatisUtils.getSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
List<Student> studentAll = mapper.findStudentAll();
for (Student student : studentAll) {
System.out.println(student);
}
}
输出结果
第二种是实现
第二种我们使用association标签来实现属性的赋值,association本来就是关联的意思,通过property和javaType来指定试题中的属性名,和实体中的数据类型,查询结果是一样的
<resultMap id="StudentInfo1" type="com.study.pojo.Student">
<id column="id" property="id"></id>
<result column="address" property="address"></result>
<result column="age" property="age"></result>
<result column="studentName" property="studentName"></result>
<!--
association:用俩关联属性
property:当前实体中的属性名称
javaType:当前实体中属性的类型
-->
<association property="stuInfo" javaType="com.study.pojo.StuInfo">
<id column="infoid" property="infoid"></id>
<result column="info_name" property="infoName"></result>
</association>
</resultMap>
<select id="findStudentAll1" resultMap="StudentInfo1">
select * from student inner join stuinfo where student.id=stuinfo.infoid
</select>
第三种实现
第三种我们也是使用association标签使用子查询来实现,我们查询学生详情就是把学生id给到学生详情来查到详情信息
select * from student;
select * from stuinfo where infoid =#{id};
StuentMappe
<resultMap id="StudentInfo2" type="com.study.pojo.Student">
<id column="id" property="id"></id>
<result column="address" property="address"></result>
<result column="age" property="age"></result>
<result column="studentName" property="studentName"></result>
<association property="stuInfo" select="com.study.mapper.StuInfoMapper.findAllStuInfo" column="id" ></association>
</resultMap>
<select id="findStudentAll2" resultMap="StudentInfo2">
select * from student
</select>
stuInfoMapper
<resultMap id="StuInfo" type="com.study.pojo.StuInfo">
<id column="infoid" property="infoid"></id>
<result column="info_name" property="infoName"></result>
</resultMap>
<select id="findAllStuInfo" resultMap="StuInfo">
select * from stuinfo where infoid = #{value}
</select>
这里我们使用association 来建立子查询,property表示要塞值的对象,select表示关联的Mapper文件的方法,column表示关联方法的入参,查询到结果包装成对象返回给主查询,在子查询中我们已经指定了属性和列之间的关系。直接返回一个对象回去,查询结果是跟之前一样的。
一对多查询
一对多查询模型
一个班有多个学生,我们在查询班级信息的时候把班里学生信息查询出来,我这里把学生详情也查出来了
sql实现
select * from student ,grade,stuinfo where student.gradeId= grade.gradeId and student.id =stuinfo.infoid
实现一个这样的效果
public interface GradeMapper {
void insertGrade(Grade grade);
List<Grade> findGradeStudent();
}
<resultMap id="GradeStudent" type="com.study.pojo.Grade">
<id column="gradeid" property="gradeid"></id>
<result column="grade_name" property="gradeName"></result>
<!--配置集合信息
property:配制集合名称
ofType:集合中的数据类型
-->
<collection property="student" ofType="com.study.pojo.Student">
<id column="id" property="id"></id>
<result column="address" property="address"></result>
<result column="age" property="age"></result>
<result column="studentName" property="studentName"></result>
<result column="gradeId" property="gradeId"></result>
<collection property="stuInfo" ofType="com.study.pojo.StuInfo">
<id column="infoid" property="infoid"></id>
<result column="info_name" property="infoName"></result>
</collection>
</collection>
</resultMap>
<select id="findGradeStudent" resultMap="GradeStudent">
select * from student ,grade,stuinfo where student.gradeId= grade.gradeId and student.id =stuinfo.infoid
</select>
我们使用collection标签来配置集合信息,property配置集合名称,ofType配置集合中的数据类型,然后是集合中的数据的一一对应关系。
@Test
public void test4(){
//获取sqlsession
SqlSession session = MybatisUtils.getSession();
GradeMapper mapper = session.getMapper(GradeMapper.class);
List<Grade> gradeStudent = mapper.findGradeStudent();
for (Grade grade : gradeStudent) {
System.out.println(grade);
}
}
运行结果,我在算是实现了一对多和一对一一块实现了
多对多查询
多对多查询模型
学生可以有很多个角色,班长,学委,团支书,一个角色可以被多个人拥有,就需要一张中间表来实现功能
数据如下
代码实现
Role类
@Data
public class Role {
private Integer RoleId;
private String RoleName;
private String desc;
}
在student中加上List Role
@Data
public class Student {
private Integer id;
private String studentName;
private Integer age;
private String address;
private Integer gradeId;
private StuInfo stuInfo;
private List<Role> roleList;
}
sql实现
select * from Student s,role r,StudentRole sr where s.id=sr.StudentId and r.RoleId = sr.RoleId
mapper
<resultMap id="StudentRole" type="com.study.pojo.Student">
<id column="id" property="id"></id>
<result column="address" property="address"></result>
<result column="age" property="age"></result>
<result column="studentName" property="studentName"></result>
<result column="gradeId" property="gradeId"></result>
<collection property="roleList" ofType="com.study.pojo.Role">
<id column="RoleId" property="RoleId"></id>
<result column="RoleName" property="RoleName"></result>
<result column="desc" property="desc"></result>
</collection>
</resultMap>
<select id="findStudentRole" resultMap="StudentRole">
select * from Student s,role r,StudentRole sr where s.id=sr.StudentId and r.RoleId = sr.RoleId
</select>
代码实现
@Test
public void test5(){
//获取sqlsession
SqlSession session = MybatisUtils.getSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
List<Student> studentRole = mapper.findStudentRole();
for (Student student : studentRole) {
for (Role role : student.getRoleList()) {
System.out.println(student.getStudentName() + "的角色有"+ role.getRoleName() +",负责"+role.getDesc());
}
}
}
Mybatis注解开发
常用注解
Mybatis也支持注解开发,减少些Mapper文件,简化开发,我们就看一些简单的crud,还是多使用xml的方式开发
public interface UserMapper {
@Select("select * from user")
List<User> selectUser();
//根据id查询
@Select("select * from user where id = #{id}")
User findUserById(Integer id);
//新增一个用户
@Insert("insert into user (name,pwd) values #{name},#{pwd})")
void InserUser(User user);
//更新用户信息
@Update(" update user set name=#{name},pwd=#{pwd} where id = #{id}")
void updateUser(User user);
// 删除用户信息
@Delete("delete from user where id=#{id}")
void deleteUserById(Integer id);
}