摘要:Mybatis笔记_04-2021.06.21,笔记内容均为观看B站视频@狂神说
Mybatis中文文档:https://mybatis.net.cn/sqlmap-xml.html
SQL 映射文件顶级元素:
cache
– 该命名空间的缓存配置。cache-ref
– 引用其它命名空间的缓存配置。resultMap
– 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。sql
– 可被其它语句引用的可重用语句块。insert
– 映射插入语句。update
– 映射更新语句。delete
– 映射删除语句。select
– 映射查询语句。
1. select
<!--通过id查询用户-->
<select id="getUserById" parameterType="int" resultType="com.riove.pojo.User">
select *
from t_user
where id = #{id}; <!-- #{}:在mapper文件中相当于之前所学的占位符"?"-->
</select>
2. insert
<!--插入一个新的用户,参数是User对象-->
<!--对象中的属性可以直接取出来-->
<insert id="addUser" parameterType="com.riove.pojo.User">
insert into t_user (id,username,password,email)
values(#{id},#{username},#{password},#{email});
</insert>
3. update
<!--通过id,修改用户信息-->
<update id="updateUserById" parameterType="com.riove.pojo.User">
update t_user
set username = #{username},password = #{password},email = #{email}
where id = #{id};
</update>
4. delete
<!--通过id,删除用户-->
<delete id="deleteUserById" parameterType="int">
delete from t_user where id = #{id};
</delete>
5.结果映射(resultMap)
结果映射:
resultMap
元素是 MyBatis 中最重要最强大的元素- 将从获取到的数据库表中的字段名,映射到程序对应实体类(JavaBean)的属性
- 在一般情况下,如果我们数据库表中的字段名与我们实体类中属性名相同时,Mybatis已经帮我们完成映射(称为隐式映射)
- 当数据库表中字段名与实体类属性名不同,需要我们在mapper文件中进行映射(称为显式映射)
作用:
- 可以让你从 90%的 JDBC
ResultSets
数据提取代码中解放出来 - 可以让你自定义字段与属性的对应关系的映射
6.简单结果集映射
resultMap:id和result区别
- id和result都是映射单列值到一个属性或字段的简单数据类型
- id一般作为标识符,如:数据库中的主键(primary key)
- result映射数据库列的字段或属性
UserMapper.java
//通过id查询用户
User getUserById(int id);
UserMapper.xml
<!--自定义结果集映射-->
<!--resutlMap标签:id,自定义名称;type,指向需要映射的实体类-->
<resultMap id="t_user" type="com.riove.pojo.User">
<!--id|result标签:column,对应数据库字段名;property,对应实体类属性名-->
<id column="id" property="t_id"/>
<result column="username" property="t_username"/>
<result column="password" property="t_password"/>
<result column="email" property="t_email"/>
</resultMap>
<!--通过id查询用户-->
<!--我们定义结果集映射,resultType|resultMap选择resultMap:引号内填写结果集id(自定义名称)-->
<select id="getUserById" parameterType="int" resultMap="t_user">
select *
from t_user
where id = #{id};
</select>
7.高级结果集映射
7.1 搭建环境
1.搭建数据库(MySQL)
-- 1.新建学生表(student)
create table student(
sno int auto_increment primary key,
sname varchar(40) not null,
tno int,
foreign key (tno) references teacher(tno)
);
insert into student(sname,tno) values("王同学",1);
insert into student(sname,tno) values("李同学",1);
insert into student(sname,tno) values("张同学",1);
insert into student(sname,tno) values("赵同学",1);
insert into student(sname,tno) values("钱同学",1);
-- 2.新建教师表(teacher)
create table teacher(
tno int auto_increment primary key,
tname varchar(40)
);
insert into teacher(tname) values("李老师");
2.搭建项目(New Module)
3.编写实体类(Student.java&Teacher.java)
package com.riove.pojo;
import java.util.List;
public class Student {
private int sno;
private String sname;
//1.多对一关系
private Teacher teacher;
public Student() {
}
public Student(int sno, String sname, Teacher teacher) {
this.sno = sno;
this.sname = sname;
this.teacher = teacher;
}
public int getSno() {
return sno;
}
public void setSno(int sno) {
this.sno = sno;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return "Student{" +
"sno=" + sno +
", sname='" + sname + '\'' +
", teacher=" + teacher +
'}';
}
}
package com.riove.pojo;
public class Teacher {
private int tno;
private String tname;
/*//2.一对多关系
private List<Student> students;*/
public Teacher() {
}
public Teacher(int tno, String tname) {
this.tno = tno;
this.tname = tname;
}
public int getTno() {
return tno;
}
public void setTno(int tno) {
this.tno = tno;
}
public String getTname() {
return tname;
}
public void setTname(String tname) {
this.tname = tname;
}
@Override
public String toString() {
return "Teacher{" +
"tno=" + tno +
", tname='" + tname + '\'' +
'}';
}
}
4.编写接口类(StudentMapper.java&TeacherMapper.java)
package com.riove.dao;
import com.riove.pojo.Student;
import java.util.List;
public interface StudentMapper {
//这个方法用于测试我们的环境是否搭建成功
// 查询所有学生信息
List<Student> getStudentList();
}
package com.riove.dao;
public interface TeacherMapper {
}
5.注册接口|注册配置文件(mybatis-config.xml)
<?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">
<!--Mybatis-->
<configuration>
<!--引入外部properties文件-->
<properties resource="db.properties">
<!--这里也可以添加相应的属性,不过调用的优先级比外部属性低-->
<!--<property name="driver" value="com.mysql.jdbc.Driver"/>-->
</properties>
<!--设置-->
<settings>
<!--全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。-->
<!--<setting name="cacheEnabled" value="true"/>-->
<!--懒加载-->
<!--<setting name="lazyLoadingEnabled" value="true"/>-->
<!--其他设置-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--类型别名-->
<typeAliases>
<!--1.全类名的类型,type="全类名",alias="自定义别名";-->
<!--<typeAlias alias="user" type="com.riove.pojo.User"/>-->
<!--2.指定包名,那么="指定的实体类包名",alias:如果没有注解,别名默认为实体类名,不区分大小写;-->
<!--<package name="com.riove.pojo"/>-->
<!--3.注解提供别名,alias:注解值;-->
<package name="com.riove.pojo"/>
</typeAliases>
<!--environments可以有多个环境,但在进行实例时只能选择一个默认环境,只有默认环境会生效-->
<environments default="mysql">
<environment id="mysql">
<!--transactionManager,事务管理:JDBC|MANAGED-->
<transactionManager type="JDBC"/>
<!--dataSource,数据源:UNPOOLED|POOLED|JNDI-->
<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>
<environment id="sqlserver">
<transactionManager type="" />
<dataSource type="">
<property name="driver" value=""/>
<property name="url" value=""/>
<property name="username" value=""/>
<property name="password" value=""/>
</dataSource>
</environment>
</environments>
<!--使用注解开发,绑定接口-->
<mappers>
<mapper class="com.riove.dao.StudentMapper"/>
<mapper class="com.riove.dao.TeacherMapper"/>
</mappers>
</configuration>
6.编写映射配置文件(StudentMapper.xml&TeacherMapper.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">
<!--namespace=帮定对应的Mapper接口(原理:相当于我们实现了这个接口)-->
<mapper namespace="com.riove.dao.StudentMapper">
<!--SQL语句: id = "接口中的方法名" resultType = “全类名,返回类型” -->
<!--这个用于测试搭建环境是否成功-->
<select id="getStudentList" resultType="student">
select * from student;
</select>
</mapper>
7.编写测试,检查环境是否搭建成功(MapperTest.java)
package com.riove.dao;
import com.riove.pojo.Student;
import com.riove.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class MapperTest {
//这个方法测试,用于检查环境是否搭建成功
@Test
public void getStudentListTest() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Student> studentList = mapper.getStudentList();
for (Student student : studentList) {
System.out.println(student);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
}
7.2 一对多关系(association:对象)
- 需求分析:查询一个老师,并查询其对应的所有学生信息
- association:当返回的变量|结果|属性是一个JavaBean对象
- - javaType="":填属性的类型
1.子查询
StudentMapper.java
//1.查询所有学生信息和任课教师
List<Student> getStudentListByAssociation_1();
StudentMapper.xml
<!--查询所有学生信息及对应任课教师信息-->
<!--
解题思路:
1.查询所有学生的信息;
2.通过外键(tno)查询教师的信息
-->
<!--1.子查询-->
<resultMap id="association_1" type="Student">
<id property="sno" column="sno"/>
<result property="sname" column="sname"/>
<!--复杂对象处理:association
private Teacher teacher → 实体类属性:teacher 类型:Teacher
tno:数据库字段
子查询:getTeacherName,获取教师信息
结果:返回teacher(教师信息)
-->
<association property="teacher" column="tno" javaType="Teacher" select="getTeacherName"/>
</resultMap>
<!--查询所有学生信息-->
<select id="getStudentListByAssociation_1" resultMap="association_1">
select * from student;
</select>
<!--子查询,获取教师信息-->
<select id="getTeacherName" resultType="Teacher">
select * from teacher;
</select>
MapperTest.java
//子查询测试
@Test
public void getStudentListByAssociation_1Test() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Student> studentList = mapper.getStudentListByAssociation_1();
for (Student student : studentList) {
System.out.println(student);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
2.连接查询
StudentMapper.java
//1.查询所有学生信息和任课教师
List<Student> getStudentListByAssociation_2();
StudentMapper.xml
<!--查询所有学生信息及对应任课教师信息-->
<!--
解题思路:
1.查询所有学生的信息;
2.通过外键(tno)查询教师的信息
-->
<!--2.连接查询:通过需要获取的结果进行查询-->
<resultMap id="association_2" type="student">
<!--数据库别名的作用:用于区别两个同名的字段,如果student和teacher中有两个name字段,可以为它们取别名用于区分-->
<id property="sno" column="id"/>
<result property="sname" column="name"/>
<!--复杂属性(对象)处理:association
private Teacher teacher → 实体类属性:teacher 类型:Teacher
-->
<association property="teacher" javaType="Teacher">
<!--此时我们处理的类为:Teacher中的属性,即该实体类中tname属性映射到数据库tname字段-->
<result property="tname" column="tname"/>
</association>
</resultMap>
<!--通过连接查询,获取结果-->
<select id="getStudentListByAssociation_2" resultMap="association_2">
select s.sno id,s.sname name,t.tname
from student s,teacher t
where s.tno = t.tno;
</select>
MapperTest.java
//连接查询测试
@Test
public void getStudentListByAssociation_2Test() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Student> studentList = mapper.getStudentListByAssociation_2();
for (Student student : studentList) {
System.out.println(student);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
7.3 多对一关系(collection:集合)
- 需求分析:查询所有学生的信息及对应的一个老师信息
- collection:当返回的变量|值|属性类型为:List集合
- JavaType="" ,填指定属性的类型
- ofType="" ,填结合中的泛型信息
1.子查询(按照顺序查询)
StudentMapper.java
//2.通过tno查询任课教师及对应的所有学生
Teacher getStudentListByCollection_2(@Param("tno") int tno);
StudentMapper.xml
<!--2.子查询,通过tno查询任课教师及对应的所有学生-->
<!--
解题思路:
1.按照tno查询对应老师的所有信息
2.查询对应老师下的所有学生
-->
<!--结果集映射:-->
<resultMap id="collection_2" type="teacher">
<id property="tno" column="tno"/>
<result property="tname" column="tname"/>
<!--复杂属性处理:List<Student> students
private List<Student> students;
javaType:List,集合
ofType:Student,集合泛型信息
select:子查询,查询对应老师下的所有学生
column="tno",最终返回类型为:Teacher,将老师的tno传到getStudentInfoByTno中,获取指定老师下的学生信息
-->
<collection property="students" javaType="ArrayList" ofType="Student" select="getStudentInfoByTno" column="tno"/>
</resultMap>
<!--按照tno-->
<select id="getStudentListByCollection_2" resultMap="collection_2">
select * from teacher where tno = #{tno};
</select>
<select id="getStudentInfoByTno" resultType="student">
select * from student s where tno = #{tno};
</select>
MapperTest.java
//连接查询测试
@Test
public void getStudentListByCollection_2Test() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
Teacher students = mapper.getStudentListByCollection_2(1);
System.out.println(students);
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
2.连接查询(按嵌套查询)
StudentMapper.java
//1.通过tno查询任课教师及对应的所有学生
Teacher getStudentListByCollection_1(@Param("tno") int tno);
StudentMapper.xml
<!--进行高级结果集映射-->
<resultMap id="collection_1" type="teacher">
<id property="tno" column="tno"/>
<result property="tname" column="tname"/>
<!--复杂属性处理:List<Student> students
private List<Student> students;
javaType:List,集合
ofType:Student,集合泛型信息
students对象中属性进行映射:sno,sname,tno
-->
<collection property="students" ofType="Student">
<id property="sno" column="sno"/>
<result property="sname" column="sname"/>
<result property="tno" column="tno"/>
</collection>
</resultMap>
<!--1.连接查询(按照结果嵌套查询)-->
<select id="getStudentListByCollection_1" resultMap="collection_1">
select t.tno,t.tname,s.sno,s.sname
from student s,teacher t
where s.tno = t.tno and t.tno = #{tno};
</select>
MapperTest.java
//子查询测试
@Test
public void getStudentListByCollection_1Test() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
Teacher students = mapper.getStudentListByCollection_1(1);
System.out.println(students);
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}