目录
一、搭建环境
二、核心配置文件
三、核心类 (测试类)
四、缓存机制
一级缓存
二级缓存
清理缓存
五、sqlMapper文件
六、单参数和多参数的传递
6.1取别名
6.2 测试新增返回自增主键
七、mybatis中Statement和PreparedStatement
作业
1、掌握环境搭建
2、掌握单个参数、多个参数的增删改查
3、缓存机制 (一级、二级缓存特点)
4、mybatis核心配置文件 常见的配置项
5、#和$的区别?(重点)
6、sqlMapper文件新增返回自增主键
7、预习 动态sql和多表关联映射
动态sql
高级结果映射
一、搭建环境
1、引入jar包
mysql.jar
mybatis.jar
2、补全结构
com.hl.pojo
com.hl.mapper
mybatis-config.xml
sqlMapper.xml
3、测试类
加载myabtis核心配置文件,得到IO流 Resources
创建sqlSessionFactory SqlsessionFactoryBuilder
SqlSession session = sqlSessionFactory.openSession()
//获取mapper接口
调用mapper方法
//关闭流
二、核心配置文件
mybatis-config.xml
<Configuration>//1、<properties resource="db.properties"></properties>//2、<environments default="test"><environment><transactionManager type="jdbc"/><dataSource type="POOLED"><property name="url" value="" ></property>usernamepassworddriver</dataSource></environment></environments>//3、<mappers><mapper resource="com/hl/mybatis01/mapper/AccountMapper.xml"/></mappers></Configuration>
补充完整代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""https://mybatis.org/dtd/mybatis-3-config.dtd">
<!--配置-->
<configuration><!--引入外部配置文件--><properties resource="db.properties"></properties>
<!--设置--><settings><!--下划线到驼峰式命名法自动映射--><setting name="mapUnderscoreToCamelCase" value="true"/></settings>
<!--类型起别名--><typeAliases><!--type="类型" alias="别名"--><!--针对每一个javabean分别起别名-->
<!-- <typeAlias type="com.hl.mybatis02.pojo.Student" alias="student"></typeAlias>--><!--统一起别名 别名默认为类名 不区分大小写--><package name="com.hl.mybatis02.pojo" /></typeAliases><!--数据库环境--><environments default="dev"><environment id="dev"><transactionManager type="jdbc"></transactionManager><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><!--mappers映射器--><mappers><!--sqlMapper文件位置-->
<!-- <mapper resource="com/hl/mybatis02/mapper/GoodsMapper.xml"></mapper>--><!--指向mapper接口位置-->
<!-- <mapper class="com.hl.mybatis02.mapper.GoodsMapper"></mapper>-->
<!-- <mapper class="com.hl.mybatis02.mapper.ItemMapper"></mapper>--><!--指向mapper包的位置,统一扫描该包下所有接口--><package name="com.hl.mybatis02.mapper"/></mappers>
</configuration>
三、核心类 (测试类)
package com.hl.mybatis02;
import com.hl.mybatis02.mapper.StudentMapper;
import com.hl.mybatis02.pojo.Student;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
class Mybatis02ApplicationTests {
@Testvoid contextLoads() throws IOException {InputStream in = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);SqlSession session = factory.openSession();StudentMapper studentMapper = session.getMapper(StudentMapper.class);
Student student = new Student(0,"admin","男","2020-1-5",1001,null,null,null);int num = studentMapper.insertStudent(student);System.out.println("受影响的数据行数:"+num);System.out.println("自增主键值为:"+student.getStudentId());session.commit();session.close();}
@Testvoid query() throws IOException {InputStream in = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);SqlSession session = factory.openSession();StudentMapper studentMapper = session.getMapper(StudentMapper.class);List<Student> list = studentMapper.listAll();System.out.println(list);
session.commit();session.close();}
}
四、缓存机制
缓存:多次执行相同dql,第一次走数据库表查询,第二次不再执行sql语句,直接从缓存区中获取数据。
一级缓存
默认已开启,可以直接使用,属于sqlSession级别的缓存。
二级缓存
默认没有开启,需要手动在mybatis配置文件中开启,属于sqlSessionFactory级别的缓存。
<!--开启当前命名空间的二级缓存-->
<cache></cache>
清理缓存
java代码清理缓存
session.clearCache();
sqlMapper文件清理缓存
useCache="false" 禁用当前sql语句的二级缓存
flushCache="true" 清空缓存区数据 导致一级缓存和二级缓存失效
<!-- //查询 下划线到驼峰式命名法的映射-->
<!-- public List<Student> listAll();useCache="false" 禁用当前sql语句的二级缓存flushCache="true" 清空缓存区数据 导致一级缓存和二级缓存失效
--><select id="listAll" resultType="student" useCache="false">select * from student</select>
示例:
@Testvoid firstCache() throws IOException {InputStream in = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);SqlSession session = factory.openSession();StudentMapper studentMapper = session.getMapper(StudentMapper.class);
List<Student> list = studentMapper.listAll();System.out.println(list);//清理缓存
// session.clearCache();List<Student> list2 = studentMapper.listAll();System.out.println(list2);
session.commit();session.close();}@Testvoid secondCache() throws IOException {InputStream in = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);SqlSession session = factory.openSession();StudentMapper studentMapper = session.getMapper(StudentMapper.class);List<Student> list = studentMapper.listAll();System.out.println(list);session.close();
SqlSession session2 = factory.openSession();StudentMapper studentMapper2 = session2.getMapper(StudentMapper.class);List<Student> list2 = studentMapper2.listAll();System.out.println(list2);session2.close();
SqlSession session3 = factory.openSession();StudentMapper studentMapper3 = session3.getMapper(StudentMapper.class);List<Student> list3 = studentMapper3.listAll();System.out.println(list3);session3.close();}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--命名空间 唯一标识-->
<mapper namespace="com.hl.mybatis02.mapper.StudentMapper">
<!--开启当前命名空间的二级缓存--><cache></cache>
五、sqlMapper文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--命名空间 唯一标识-->
<mapper namespace="com.hl.mybatis02.mapper.StudentMapper"><!-- 测试自增主键的生成useGeneratedKeys="true" 获取自动生成的主键keyProperty="studentId" 主键对应的属性名-->
<!-- public int insertStudent(Student student);--><insert id="insertStudent" useGeneratedKeys="true" keyProperty="studentId">insert into student(name,gender,birth_date,class_id,enrollment_date)values (#{name},#{gender},#{birthDate},#{classId},now())</insert>
<!-- //查询 下划线到驼峰式命名法的映射-->
<!-- public List<Student> listAll(); --><select id="listAll" resultType="student">select * from student</select>
</mapper>
六、单参数和多参数的传递
6.1取别名
Mapper接口
测试新增主键的生成,对象也可以取别名
多个参数,给参数起别名,将不再使用系统默认的arg0、arg1等
单个参数,也可以取别名,之后#{里面不能随便写了只能写别名}
//测试新增主键的生成,对象也可以取别名public int insertStudent(@Param("stu")Student student);
// 查询 下划线到驼峰式命名法的映射public List<Student> listAll();// 多个参数,给参数起别名,将不再使用系统默认的arg0、arg1等public List<Student> findStudent(@Param("name")String name, @Param("phone")String phone);
// 单个参数,也可以取别名,之后#{里面不能随便写了只能写别名}public Student findStudentById(int id);
6.2 测试新增返回自增主键
Mapper映射文件里面
测试新增主键的生成:
useGeneratedKeys="true" 获取自动生成的主键
keyProperty="studentId" 主键对应的属性名
对象在接口中取别名之后,调用对象的属性名,应该写成:别名.属性名
<!--命名空间 唯一标识-->
<mapper namespace="com.hl.mybatis02.mapper.StudentMapper"><!-- //测试新增主键的生成
useGeneratedKeys="true" 获取自动生成的主键
keyProperty="studentId" 主键对应的属性名
对象在接口中取别名之后,调用对象的属性名,应该写成:别名.属性名
-->
<!-- public int insertStudent(Student student);--><insert id="insertStudent" useGeneratedKeys="true" keyProperty="studentId">insert into student(name,gender,birth_date,class_id,enrollment_date)values (#{stu.name},#{stu.gender},#{stu.birthDate},#{stu.classId},now())</insert><!-- // 查询 下划线到驼峰式命名法的映射-->
<!-- public List<Student> listAll();--><select id="listAll" resultType="student">select * from student</select><!-- // 多个参数-->
<!-- public List<Student> findStudent(String name,String phone);--><!-- select * from student where name = #{arg0} and phone = #{arg1}--><!-- <select id="findStudent" resultType="student">-->
<!-- select * from student where name = #{name} and phone = #{phone}-->
<!-- </select>-->
<!-- 模糊查询--><select id="findStudent" resultType="student">select * from student where name like concat('%',#{name},'%') or phone = #{phone}</select><!-- 单个参数-其实识别的不是id是里面的第一个参数-->
<!-- public List<Student> findStudentByName(int id);--><select id="findStudentById" resultType="student">select * from student where student_id = #{iaa}</select></mapper>
七、mybatis中Statement和PreparedStatement
statementType="PREPARED" 默认 使用预编译(防止sql注入)
statementType="STATEMENT" sql 字符串拼接
statementType="CALLABLE" 调用存储过程
<!-- //多个参数
public List<Student> findStudents(String name,String phone);
statementType="PREPARED" 默认 使用预编译STATEMENT sql字符串拼接CALLABLE 调用存储过程
-->
<select id="findStudents" resultType="Student">select * from student where name like concat('%',#{name},'%') or phone=#{phone}
</select>
<!--public Student findStudentById(int id);-->
<select id="findStudentById" resultType="Student" statementType="STATEMENT">select * from student where student_id=${id}
</select>
作业
1、掌握环境搭建
2、掌握单个参数、多个参数的增删改查
3、缓存机制 (一级、二级缓存特点)
4、mybatis核心配置文件 常见的配置项
5、#和$的区别?(重点)
-
预处理方式不同
-
#{}
:使用预编译(PreparedStatement)方式,参数会被替换为?
,能有效防止 SQL 注入 -
${}
:使用字符串拼接方式,直接将参数值替换到 SQL 语句中
-
-
安全性
-
#{}
:安全,能防止 SQL 注入 -
${}
:不安全,存在 SQL 注入风险
-
-
参数处理
-
#{}
:会对传入的参数自动添加引号(字符串类型) -
${}
:原样替换,不会添加引号
-
6、sqlMapper文件新增返回自增主键
见6.2
7、预习 动态sql和多表关联映射
动态sql
-
if
-
choose (when, otherwise)
-
trim (where, set)
-
foreach
高级结果映射
MyBatis 创建时的一个思想是:数据库不可能永远是你所想或所需的那个样子。 我们希望每个数据库都具备良好的第三范式或 BCNF 范式,可惜它们并不都是那样。 如果能有一种数据库映射模式,完美适配所有的应用程序,那就太好了,但可惜也没有。 而 ResultMap 就是 MyBatis 对这个问题的答案。
比如,我们如何映射下面这个语句?
<!-- 非常复杂的语句 -->
<select id="selectBlogDetails" resultMap="detailedBlogResultMap">selectB.id as blog_id,B.title as blog_title,B.author_id as blog_author_id,A.id as author_id,A.username as author_username,A.password as author_password,A.email as author_email,A.bio as author_bio,A.favourite_section as author_favourite_section,P.id as post_id,P.blog_id as post_blog_id,P.author_id as post_author_id,P.created_on as post_created_on,P.section as post_section,P.subject as post_subject,P.draft as draft,P.body as post_body,C.id as comment_id,C.post_id as comment_post_id,C.name as comment_name,C.comment as comment_text,T.id as tag_id,T.name as tag_namefrom Blog Bleft outer join Author A on B.author_id = A.idleft outer join Post P on B.id = P.blog_idleft outer join Comment C on P.id = C.post_idleft outer join Post_Tag PT on PT.post_id = P.idleft outer join Tag T on PT.tag_id = T.idwhere B.id = #{id}
</select>
你可能想把它映射到一个智能的对象模型,这个对象表示了一篇博客,它由某位作者所写,有很多的博文,每篇博文有零或多条的评论和标签。 我们先来看看下面这个完整的例子,它是一个非常复杂的结果映射(假设作者,博客,博文,评论和标签都是类型别名)。 不用紧张,我们会一步一步地来说明。虽然它看起来令人望而生畏,但其实非常简单。
<!-- 非常复杂的结果映射 -->
<resultMap id="detailedBlogResultMap" type="Blog"><constructor><idArg column="blog_id" javaType="int"/></constructor><result property="title" column="blog_title"/><association property="author" javaType="Author"><id property="id" column="author_id"/><result property="username" column="author_username"/><result property="password" column="author_password"/><result property="email" column="author_email"/><result property="bio" column="author_bio"/><result property="favouriteSection" column="author_favourite_section"/></association><collection property="posts" ofType="Post"><id property="id" column="post_id"/><result property="subject" column="post_subject"/><association property="author" javaType="Author"/><collection property="comments" ofType="Comment"><id property="id" column="comment_id"/></collection><collection property="tags" ofType="Tag" ><id property="id" column="tag_id"/></collection><discriminator javaType="int" column="draft"><case value="1" resultType="DraftPost"/></discriminator></collection>
</resultMap>