环境:
- jdk 1.8
- mysql:8.0
- maven:3.6.3
知识:
- JDBC
- Mysql
- Java基础
- Maven
- Junit
文章目录
maven配置官网:https://mvnrepository.com/
mybatis中文文档:https://mybatis.org/mybatis-3/zh/index.html
一、简介
1.1 什么是Mybatis
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
1.2 如何获得Mybatis
- maven仓库:pom配置
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
1.3 为什么用Mybatis
传统的JDBC代码太复杂,简化为框架。帮助程序员将数据存储到数据库
二、写Mybatis程序
搭建环境→导入Mybatis→编写代码→测试
2.1 搭建环境(导入依赖)
- 搭建数据库
CREATE DATABASE mybatis;
use mybatis;
CREATE TABLE user(
id int PRIMARY KEY auto_increment,
name varchar(30),
pwd varchar(30)
);
INSERT into user VALUES
(1,'张三','666'),
(2,'李四','777'),
(3,'王五','888');
- 新建一个Maven普通项目,删除src文件夹,在pom中导入依赖(记得设置使用的maven版本以及路径)
2.2 XML 中构建 SqlSessionFactory
- 创建一个新的模块,在main-resources下编写mybatis的核心配置文件(在idea中导入数据库)
注意:drvier地址、url地址,以及后面的Mapper.xml配置不能忘
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">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC "/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/study/dao/UserMapper.xml"/>
</mappers>
</configuration>
-
编写mybatis工具类
获取 sqlSessionFactory 从而获取sqlSession实例
注意:resources地址不能写错
/**
* 工具类
*/
public class MybatisUtil {
private static SqlSessionFactory sqlSessionFactory;
static {
try{
//获取 sqlSessionFactory 对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}catch (Exception e){
e.printStackTrace();
}
}
//获取SqlSession实例
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
2.3 编写实体类、Mapper接口
Mybatis里的Mapper相当于JDBC中的DAO
- 编写实体类
package com.study.pojo;
public class User {
private int id;
private String name;
private String pwd;
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public User() {
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getPwd() {
return pwd;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
- 编写Mapper接口
public interface UserMapper {
public List<User> selectUser();
}
- 编写UserMapper.xml配置文件
注意: resultType要写路径
<?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.study.dao.UserMapper">
<select id="selectUser" resultType="com.study.pojo.User"><!--id中尽量和方法名保持一致-->
select * from user
</select>
</mapper>
2.4测试代码
- 在mybatis-config.xml文件中,配置mapper.xml文件路径
<mappers>
<mapper resource="com/study/dao/UserMapper.xml"/>
</mappers>
- 在pom.xml文件中build标签内配置resource节点,使src//main//.xml配置文件可以导出
<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>
- 开始测试
public class UserMapperTest {
@Test
public void test(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
System.out.println(sqlSession);
List<User> users = sqlSession.selectList("com.study.dao.UserMapper.selectUser");//映射到xml文档的命名空间的id
for(User temp:users){
System.out.println(temp.toString());
}
/*更优方式*/
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.selectUser();
for(User temp:users){
System.out.println(temp.toString());
}
sqlSession.close();
}
}
2.5 总结
首先要有一个maven项目,导入mysql、junit、mybatis的依赖,配置pom文件;
然后要有pojo中的实体类对应数据库中的表
要有UserMapper功能接口
要有MybatisUtis类获取sqlSession
- mybatis-config.xml (配置数据库信息)负责连接上数据库,通过配置mapper标签连接上 UserMapper.xml文件
- UserMapper.xml文件连接UserMapper接口(也就是UserDAO)以及其中的方法,select标签实现接口中的方法
- 测试方法获取sqlSession时,获取sqlSession时在MybatisUtis类要加载mybatis-config.xml的流信息。sqlSession调用接口中的方法获取查询结果。
三、CRUD操作
3.1 增删改查
注意:命名空间【namespace】 为接口路径 、【id】为接口中对应的方法名、【resultType】为返回类(指定路径)、【parameterType】为参数类型,参数用 #{ 具体属性 }
- 接口
public interface UserMapper {
List<User> selectUser();
int insertUser(User user);
int deleteUser(int id);
int updateUser(User user);
}
- UserMapper.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.study.dao.UserMapper">
<select id="selectUser" resultType="com.study.pojo.User">
select * from user
</select>
<insert id="insertUser" parameterType="com.study.pojo.User" >
insert into mybatis.user (name, pwd) values (#{name },#{pwd})
</insert>
<delete id="deleteUser" parameterType="int" >
delete from mybatis.user where id=#{id};
</delete>
<update id="updateUser" parameterType="com.study.pojo.User">
update mybatis.user set name=#{name },pwd=#{pwd} where id=#{id};
</update>
</mapper>
- 测试·
@Test
public void selectUser(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.selectUser();
for(User temp:users){
System.out.println(temp.toString());
}
sqlSession.close();
}
@Test
public void insertUser(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int res = mapper.insertUser(new User("阿珂", "ake"));
System.out.println("修改是否成功 res="+res);
sqlSession.commit();//提交事务
sqlSession.close();
}
@Test
public void deleteUser(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int res = mapper.deleteUser(5);
System.out.println("删除是否成功 res="+res);
sqlSession.commit();//提交事务
sqlSession.close();
}
@Test
public void updateUser(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int res = mapper.updateUser(new User(2, "大哥", "999"));
System.out.println("更新是否成功 res="+res);
sqlSession.commit();//提交事务
sqlSession.close();
}
3.2 使用Map作为参数
当只有一个参数类型的时候,可以直接取到
当有多个参数类型的时候,可以使用 parameterType=“com.study.pojo.User”
同时,也可以使用 parameterType=“map”
- 示例:
UserMapper接口方法
int updateUser2(Map<String,Object> map); /* 引入 map */
UserMapper.xml
<!--引入map-->
<update id="updateUser2" parameterType="map">
update mybatis.user set pwd=#{password} where id=#{id};
</update>
@Test
public void updateUser2(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
/**
* 在这里 只修改 id为2 的密码为 000
* 若是使用原来的 user 类,并且在属性非常多乃至成百上千,则 new 一个 User 只修改 密码 就非常麻烦
* 所以引入 Map
*/
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("id",2);
map.put("password","000");
int res = mapper.updateUser2(map);
System.out.println("更新是否成功 res="+res);
sqlSession.commit();//提交事务
sqlSession.close();
}
3.3 模糊查询
当进行模糊查询的时候,应当将通配符写在UserMapper.xml配置文件中,防止sql注入。
UserMapper.xml 配置文件
<select id="selectUser2" resultType="com.study.pojo.User">
select * from mybatis.user where name like "%"#{value}"%";
</select>
查询代码
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.selectUser2("张");
四、配置解析
4.1 核心配置文件
mybatis-config.xml
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
4.2 环境配置
MyBatis 可以配置成适应多种环境,不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
<environments default="development"><!--通过id选择某种环境配置-->
<environment id="development">
<transactionManager type="JDBC"/> <!--事务管理器 JDBC/MANAGED -->
<dataSource type="POOLED"> <!--数据源:配置 JDBC 连接对象的资源。 这里是数据库连接池
有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]")-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC "/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
4.3 属性
我们可以通过properties属性来实现引用配置文件
这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。
可以直接引入外部文件
也可以在<properties>标签下添加子标签<property name="" value=""/>添加配置信息
若两个方法同时使用并且属性重复赋值不相同,则优先读取外部文件
<?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="db.properties"></properties> <!--引入外部配置文件-->
<environments default="development">
<environment id="development">
<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>
<mappers>
<mapper resource="com/study/dao/UserMapper.xml"/>
</mappers>
</configuration>
4.4 类型别名
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。
示例:
要卸载配置文件的第三位,若无settings,则写在 properties 后面
- 方式一:指定到全类名(实体类较少时推荐使用)
mybatis-config.xml
<!--类型别名-->
<typeAliases>
<typeAlias type="com.study.pojo.User" alias="User"/>
</typeAliases>
- 方式二:指定到包(实体类较多时推荐使用,若需要自定义别名,可用注解)
<typeAliases>
<package name="com.study.pojo"/><!--别名默认为 包 下面的类名首字母小写 user -->
</typeAliases>
- 方式三:使用注解
@Alias("user")/*别名就为 user */
public interface UserMapper {}
UserMapper.xml
<select id="selectUser2" resultType="User"><!--别名就代表全类名-->
select * from mybatis.user where name like "%"#{value}"%";
</select>
4.5 映射器
绑定注册Mapper.xml文件
- 方式一: 使用相对于类路径的资源引用
<mappers>
<mapper resource="com/study/dao/UserMapper.xml"/>
</mappers>
- 方式二:使用映射器接口实现类的完全限定类名
注意:接口和Mapper配置文件必须同名,并且必须在同一个包下。
<mappers>
<mapper class="com.study.dao.UserMapper"/>
</mappers>
- 方式三:将包内的映射器接口实现全部注册为映射器
<mappers>
<package name="com.study.dao"/>
</mappers>
4.6 生命周期和作用域
生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题。
-
SqlSessionFactoryBuilder:
一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量) -
SqlSessionFactory:
SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
- SqlSession(作用如上图)
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
五、ResultMap(结果集映射)
5.1 问题
当Bean对象的属性名和数据库中的列名不一致,就会出现问题
5.2 解决
若方法名也是 setPassword ,也可以解决!
UserMapper.xml
<resultMap id="UserMap" type="user">
<result property="id" column="id"/><!--可以省略掉相同的-->
<result property="name" column="name"/>
<result property="password" column="pwd"/>
</resultMap>
<select id="selectUser2" resultMap="UserMap">
select * from mybatis.user where name like "%"#{value}"%";
</select>
六、日志
6.1 日志工厂
内置日志工厂
SLF4J
Apache Commons Logging
Log4j 2
Log4j
JDK logging
可选值
SLF4J、LOG4J、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、NO_LOGGING
mybatis-config.xml
<settings>
<!--标准的日志工厂,控制台输出-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
控制台输出日志
6.2 Log4j
- 什么是Log4j
Log4j是Apache的一个开源项目
通过使用Log4j,我们可以控制日志信息输送的目的地:控制台,文本,GUI组件…我们也可以控制每一条日志的输出格式;
通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。 - 使用步骤
1.配置pom文件,导入log4j的jar包
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
- mybatis-conf.xml 添加设置
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
- 配置log4j.properties文件(网上可以查找配置详解)
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/log4jInfo.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
- 在程序中使用log4j输出
测试程序
import org.apache.log4j.Logger;
public class UserMapperTest {
static Logger logger = Logger.getLogger(UserMapperTest.class);
@Test
public void selectUser2(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
logger.info("info:log4j输出日志");
logger.debug("debug:log4j输出日志");
logger.error("error:log4j输出日志");
List<User> users = mapper.selectUser2("张");
for(User temp:users){
System.out.println(temp.toString());
}
sqlSession.close();
}
}
七、分页查询
7.1 使用sql分页查询
userMapper.xml
<select id="selectUser" resultType="User" parameterType="map">
select * from user limit ${startIndex},${endIndex}
</select>
测试程序
@Test
public void selectUser(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String,Object> map = new HashMap<String,Object>();
map.put("startIndex","0");
map.put("endIndex","2");
List<User> users = mapper.selectUser(map);
for(User temp:users){
System.out.println(temp.toString());
}
sqlSession.close();
}
查询结果
7.2 使用RowBounds
UserMapper.xml
<select id="rowBounds" resultType="User">
select * from mybatis.user
</select>
测试
@Test
public void testRowBounds(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
RowBounds rowBounds = new RowBounds(1,2);//下标 1 开始,一页2行
List<User> list = sqlSession.selectList("com.study.dao.UserMapper.rowBounds",null ,rowBounds);
for(User temp:list){
System.out.println(temp);
}
sqlSession.close();
}
八、使用注解开发
- 不使用UserMapper.xml文件,用注解代替,但是有一定的局限性
接口
public interface UserMapper {
@Select("select * from user")
List<User> getUser();
/*
方法若是存在基本类型参数 可使用 @Param("")
@Select("select #{name} from user where id=#{id}")
List<User> getUser( @Param("id") int id, @Param("name") int name);
*/
}
使用Map
@Select("select * from user limit #{startIndex},#{endIndex}")
List<User> selectUser(Map<String,Object> map);
删除
@Delete("delete from user where id = #{uid}")
int deleteUser(@Param("uid") int id);
修改:
@Update("update user set name=#{name},pwd=#{password} where id = #{id}")
int updateUser(User user);
绑定接口
mybati-config.xml
<mappers>
<mapper class="com.study.dao.UserMapper"/>
</mappers>
测试
@Test
public void testAnnotation(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> user = mapper.getUser();
for(User temp:user){
System.out.println(temp);
}
sqlSession.close();
}
九、多对一 和 一对多
对于学生和老师的关系,我们假定如图所示:
老师对学生是 一对多,老师则是对象(association),学生就是集合(clloection)
9.2 多对一
按照查询嵌套处理
studentMapper.java
public interface StudentMapper {
List<Student> getStudent();
}
studentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.study.dao.StudentMapper">
<select id="getStudent" resultMap="studentTeacher">
select * from student
</select>
<resultMap id="studentTeacher" type="Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
<!-- 本质: select * from teacher where id = 【column】 -->
</resultMap>
<select id="getTeacher" resultType="Teacher">
select * from mybatis.teacher where id=#{tid}
</select>
</mapper>
查询结果
按照结果嵌套处理
studentMapper.java
List<Student> getStudent2();
studentMapper.xml
<select id="getStudent2" resultMap="studentTeacher2">
select s.id sid,s.name sname,t.name tname,t.id tid
from teacher t,student s
where s.tid = t.id
</select>
<resultMap id="studentTeacher2" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
<result property="id" column="tid"/>
</association>
</resultMap>
查询结果:
9.3 一对多
按照查询嵌套处理
List<Teacher> getTeacher2(@Param("tid") int id);
<select id="getTeacher2" resultMap="TeacherStudent2">
select * from teacher where id = #{tid}
</select>
<resultMap id="TeacherStudent2" type="Teacher">
<result property="id" column="id"/>
<result property="name" column="name"/>
<collection property="students" javaType="List" ofType="Student" column="id"
select="getStudentByTeacherId"/>
<!-- 本质: select * from student where tid = 【column】 -->
</resultMap>
<select id="getStudentByTeacherId" resultType="Student">
select * from student where tid = #{tid}
</select>
按照结果嵌套处理
List<Teacher> getTeacher(@Param("tid") int id);
<select id="getTeacher" resultMap="TeacherStudent">
select t.name tname,t.id tid,s.id sid,s.name sname,s.tid stid
from teacher t,student s
where t.id = s.tid and t.id = #{tid}
</select>
<resultMap id="TeacherStudent" type="Teacher">
<result property="name" column="tname"/>
<result property="tid" column="id"/>
<collection property="students" ofType="Student" >
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="sid"/>
</collection>
</resultMap>
十、动态SQL
什么是动态SQL:根据不同的查询条件,生成不同的SQL语句。
10.1 搭建环境
数据表
pojo类
10.2 If 语句判断
BlogMapper.java
List<Blog> queryBlog(Map map);
/*
传入参数map ,若包含 title 或 author ,则按字段查询,否则全部查询
*/
BlogMapper.xml
<select id="queryBlog" parameterType="map" resultType="blog">
select *
from mybatis.blog
where 1=1
<if test="title!=null">
and title = #{title}
</if>
<if test="author!=null" >
and author = #{author}
</if>
</select>
测试
@Test
public void test(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap();
map.put("title","Java");
map.put("author","狂神说");
List<Blog> blogs = mapper.queryBlog(map);
for(Blog blog:blogs){
System.out.println(blog);
}
sqlSession.close();
}
10.2 常用标签
choose when orherwise
where 、trim
set
foreach
index 属性可以不用,传递进来的参数 parameterType=“map”,map.put(“list”,new ArrayList())
SQL片段
为了将大量重复的 sql 语句提取出来,减少冗余。
- 提取SQL片段
<sql id="if-title-author">
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</sql>
- 引用SQL片段
<select id="queryBlogIf" parameterType="map" resultType="blog">
select * from blog
<where>
<include refid="if-title-author"></include>
</where>
</select>
十一、缓存
11.1 简介
11.2 mybatis缓存
MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。
- 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)
- 二级缓存需要手动开启和配置,他是基于 namespace级别的缓存
- 为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现 Cache接口来 自定义二级缓存
可选缓存策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
11.3 一级缓存
一级缓存是SqlSession级别的缓存,是一直开启的,我们关闭不了它;
一级缓存失效情况:没有使用到当前的一级缓存,效果就是,还需要再向数据库中发起一次查询请求!
- 一级缓存失效的四种情况(缓存刷新):
- 使用不同的 sqlSession 发送SQL语句
- sqlSession相同,但查询不同的记录
- 在两次相同查询之间,进行了增删改操作
- 手动清理缓存 sqlSession.clearCache
11.4 二级缓存
- 二级缓存又称全局缓存
- 基于 namespace级别的缓存,一个名称空间,对应一个二级缓存(对应一个Mapper.xml)文件
-
使用步骤:
- 显式开启全局缓存
<setting name="cacheEnabled" value="true"/>
- 去Mapper.xml文件中配置 <cache/>标签,也可以添加属性信息。
- 代码测试:对应的实体类要先实现序列化接口
-
结论
- 只要开启了二级缓存,我们在同一个Mapper中的查询,可以在二级缓存中拿到数据
- 查出的数据都会被默认先放在一级缓存中,只有会话提交或者关闭以后,一级缓存中的数据才会转到二级缓存中