问题引入:
一张学生表和一张老师表,它们通过tid外键联系起来,查询学生的时候,同时将老师表里的老师也查询出来。
分析:
查询多个学生和自己的老师
多个学生对应一个老师
对于学生而言,关联 多个学生关联一个老师
对于老师而言,集合 一个老师有多个学生
思路:
select s.id,s.name as studentName,t.name as teacherName
from mydatabase.student s,mydatabase.teacher t
where s.tid = t.id;
所以,实际应用中,对数据库的操作,必然是会涉及多张表的,这在面向对象中就涉及对象与对象之间的关联关系,针对多张表之间的操作,Mybatis提供了关系映射。
1、搭建环境
<!--在build中配置文件resources,来防止我们资源导出失败的问题-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
2、配置文件
db.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydatabase?
username=root
password=123456
Mybatis-config.xml
<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--引入jdbc文件-->
<properties resource="db.properties"/>
<!--取别名-->
<typeAliases>
<package name="com.pojo"/>
</typeAliases>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!--注册mapper-->
</configuration>
3、提取工具类,以便复用
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
String resource = "Mybatis-config.xml";
try{
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession(true);
}
}
4、创建实体类,与数据库对应
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private int id;
private String name;
//在学生中关联一个老师
private Teacher teacher;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
private int id;
private String name;
}
5、搭建dao接口
public interface StudentMapper {
List<Student> getStudent();
List<Student> getStudent2();
}
public interface TeacherMapper {
Teacher getTeacher(int id);
}
6、解决方式
association元素
在result元素中有一个子元素association,Mybatis中就是通过这个元素来处理一对一,多对一关联关系的。
association中的主要属性:
javaType:完整Java类名或别名。
property:映射数据库列的实体类中对象的属性名。column:数据库列名或别名
id:主键 property:主键在实体类中的属性名。column:数据库中的主键名
select:指定引入嵌套查询的子SQL语句,用于关联映射中的嵌套查询(重点)
1、嵌套 查询
就是把查询利用select嵌套在一起,实现一对一的查询
在StudentMapper.xml中
<select id="getStudent" resultMap="StudentOfTeacher">
select * from mydatabase.student;
</select>
<resultMap id="StudentOfTeacher" type="Student">
<!--设置主查询中的主键-->
<id property="id" column="id"/>
<result property="name" column="name"/>
<association property="teacher" column="tid"
javaType="Teacher"
select="getTeacher"> <!--方式一-->
<!-- select="com.dao.TeacherMapper.getTeacher"> 方式二和三-->
<!--设置次查询中的主键-->
<id property="id" column="id"/>
</association>
</resultMap>
select=“path”
方式一
直接在TeacherMapper接口中编写一个注解查询,使用方法名引入
public interface TeacherMapper {
@Select("select * from mydatabase.teacher where id = #{id} ")
Teacher getTeacher(int id);
}
方式二
直接在StudentMapper.xml中直接编写,可以直接使用id在association引入
<select id="getTeacher" parameterType="int" resultType="Teacher">
select * from mydatabase.teacher where id = #{id}
</select>
方式三
在TeacherMapper.xml中编写,利用id引入
<select id="getTeacher" parameterType="int" resultType="Teacher">
select * from mydatabase.teacher where id = #{id}
</select>
2、嵌套 结果
将查询结果嵌套起来
<select id="getStudent2" resultMap="StudentOfTeacher2">
select s.id as sid,s.name as sname,t.name as tname,t.id as tid
from mydatabase.student s,mydatabase.teacher t
where s.tid = t.id;
</select>
<resultMap id="StudentOfTeacher2" type="Student">
<id property="id" column="sid"/>
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<id property="id" column="tid"/>
<result property="name" column="tname"/>
</association>
</resultMap>
结果:
7、遇到的问题
出现teacher=Teacher(id=0,name=秦老师)中的id=0
解决办法:在association中设置主键,或者在association中添加 result property=“id” column=“tid”
实际就是查询的时候,无法找到老师的id映射关系,所以查不到
解决办法:将xml的所有UTF-8设置为UTF8