目录

一.简介

1.什么是mybatis

2.优点

二.第一个Mybatis程序

1.搭建环境

2.新建项目

三.CRUD

1.参数

2.select

3.Insert

4.update

5.delete

6.模糊查询

四.配置解析

1.核心配置文件

2.环境变量(environments)

3.属性(properties)

4.类型别名

5.设置(settings)

6.映射器

7.声明周期和作用域

五.解决属性名和列名不一致的问题

方法一:起别名

方法二:resultMap

六.日志

1.日志工厂

2.Log4j

七. 分页

1.使用limmit技术进行分页

2.RowBounds分页

八.使用注解开发

九.Lombok

十.复杂查询

1.多对一处理

按照结果嵌套处理

按照查询嵌套处理

2.一对多处理

按照结果嵌套处理

按照查询嵌套处理

十一.动态SQL

搭建环境

IF语句

Choose语句

trim(Where,set)

SQL片段

Foreach

12.缓存

1.简介

2. Mybatis缓存

3.一级缓存

4缓存失效

4.二级缓存


一.简介

1.什么是mybatis

1.MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。

2.MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。

3.MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

2.优点

sql和代码的分离,提高可维护性

提供映射标签,支持对象与数据库的orm字段关系映射

提供对象关系映射标签,支持对象关系组建维护

提供xml标签,支持编写动态sql

二.第一个Mybatis程序

思路:搭建环境->导入Mybatis->编写代码->测试

1.搭建环境

(1)搭建数据库

CREATE DATABASE mybatis;CREATE TABLE user(
id INT(20) NOT NULL PRIMARY KEY,
name VARCHAR(30) DEFAULT NULL,
pwd VARCHAR(30) DEFAULT NULL
) ENGINE=INNODB DEFAULT CHARSET=utf8;
//设置引擎和字符集
use mybatis;insert into user(id,name,pwd)values(1,'貂蝉','123456'),(2, '孙尚香', '123456'),(3, '小乔', '123890');

2.新建项目

1.pom.xml

<dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.17</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.2</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version></dependency></dependencies>

2.mybatis核心配置文件

mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//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"></transactionManager><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://10.2.4.232:3306/mybatis?useUnicode=true&amp;characterEncoding=utf8"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments><mappers><mapper resource="UserMapper.xml"></mapper></mappers>
</configuration>

3.mybatis工具类

package util;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 java.io.IOException;
import java.io.InputStream;/*** @description:编写mybatis工具类*/
public class MybatisUtil {private MybatisUtil(){}public static SqlSession getSqlSession(){String resources="mybatis-config.xml";InputStream inputStream=null;SqlSession sqlSession = null;//获取SqlSessionFactory对象try {inputStream= Resources.getResourceAsStream(resources);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//从sqlSessionFactory中获取sqlsessionsqlSession = sqlSessionFactory.openSession();} catch (IOException e) {e.printStackTrace();}return sqlSession;}
}

4.实体类

package pojo;public class User {private int id;private String name;private String pwd;public User() {}public User(int id, String name, String pwd) {this.id = id;this.name = name;this.pwd = pwd;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", pwd='" + pwd + '\'' +'}';}
}

5.mapper接口

public interface UserMapper {List<User> getList();}

6.接口实现

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao.UserMapper"><select id="getList" resultType="pojo.User">select * from user</select>
</mapper>

7.测试

public class UserMapperTest {@Testpublic void test() {//第一步:获得sqlsession对象SqlSession sqlSession = MybatisUtil.getSqlSession();System.out.println(sqlSession);//方式一: getMapperList<User> userlist = sqlSession.getMapper(UserMapper.class).getUserList();sqlSession.close();

三.CRUD

1.参数

namespace: namespace中的包名要和Dao/mapper接口的包名一致!

id:就是对应的namespace中的方法名;

resultType: Sq|语句执行的返回值!

parameterType :参数类型!

2.select

1.接口方法

 List<User> getList();User getListById(int id);

2.编写对应的mapper中的sq|语句

<select id="getList" resultType="pojo.User">select * from user
</select>  <select id="getListById" resultType="pojo.User" parameterType="int">           select * from mybatis.user where id=#{id}
</select>

3.测试

@Testpublic void getUserById() {SqlSession sqlSession = MybatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = mapper.getUserById(1);System.out.println(user);sqlSession.close();}

3.Insert

1.接口

int addUser(User user);

2.编写对应的mapper中的sq|语句

 <insert id="addUser"  parameterType="pojo.User" >insert into mybatis.user (id,name,pwd)values (#{id},#{name},#{pwd})</insert>

3.测试

 @Testpublic void addUser() {SqlSession sqlSession = MybatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);int res = mapper.addUser(new User(5, "哈哈", "123333"));if (res > 0) {System.out.println("插入成功!");}//提交事务sqlSession.commit();sqlSession.close();}

4.update

1.接口

int updateUser(User user);

2.编写对应的mapper中的sq|语句

<update id="updateUser" parameterType="pojo.User">update mybatis.user set name =#{name},pwd=#{pwd} where id=#{id}</update>

3.测试

 @Testpublic void updateUser(){SqlSession sqlSession = MybatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper . class);mapper.updateUser(new User(4,"呵呵","123123"));sqlSession.commit();sqlSession.close();}

5.delete

1.接口

 void deleteUser(int id);

2.编写对应的mapper中的sq|语句

 <delete id="deleteUser" parameterType="int">delete from mybatis.user where id=#{id}</delete>

3.测试

@Testpublic void deleteUser(){SqlSession sqlSession = MybatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);mapper.deleteUser(4);sqlSession.commit();sqlSession.close();}

6.模糊查询

1.接口

User getListBylike(String str);

2.编写对应的mapper中的sq|语句

 <select id="getListBylike" parameterType="String" resultType="pojo.User">select * from mybatis.user where name like "%"#{name}"%"</select>

3.测试

@Testpublic void test(){//第一步获取sqlsessionSqlSession sqlSession = MybatisUtil.getSqlSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);User user = userMapper.getListBylike("白");System.out.println(user);sqlSession.commit();sqlSession.close();}

四.配置解析

1.核心配置文件

  • mybatis-config.xml
  • MyBatis的配置文件包含了影响MyBatis行为的设置和属性信息。
properties(属性)
settings(设置)
typeAliases(类型别名)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)

2.环境变量(environments)

MyBatis可以配置成适应多种环境,但每个SqlSessionFactory实例只能选择一种环境。
MyBatis默认的事务管理器就是JDBC,连接池:POOLED

    <environments default="development"> 更改default为test,即可切换到第二套环境。<environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment><environment id="test"><transactionManager type=""></transactionManager><dataSource type=""></dataSource></environment></environments>

3.属性(properties)

通过properties属性来实现引用配置文件。属性可外部配置且可动态替换,既可在典型的java属性文件中配置,亦可通过properties元素的子元素传递。文件:【db.properties】

在resources下编写配置文件:

db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8
username=root
password=123456

在核心配置文件中引入

<!--    引入外部配置文件--><properties resource="db.properties"><property name="username" value="root"/><property name="password" value="11111"/></properties>
0
  • 可以直接引入外部文件,db.properties。
  • 可以在其中增加一些属性配置。
  • 如果两个文件有同一个字段,优先使用外部配置文件的内容。

修改相应的environment配置:

 <environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/>   here<property name="url" value="${url}"/>     here<property name="username" value="${username}"/>  here<property name="password" value="${password}"/>   here</dataSource></environment></environments>

4.类型别名

  • 类型别名是为java类型设置一个短的名字。
  • 用来减少类完全限定名的冗余。
<!--    方式一-->
<!--    给实体类取别名--><typeAliases><typeAlias type="com.kuang.pojo.User" alias="User"/></typeAliases>

可以指定一个包名,MyBatis会在包名下面搜索需要的Java Bean,扫描实体类的包,它的默认别名就为这个类的类名,首字母小写。

<!--    方式二--><typeAliases><package name="com.kuang.pojo"/></typeAliases>
  • 在实体类比较少的时候,使用第一种。
  • 如果实体类比较多,建议使用第二种。

5.设置(settings)

<settings><setting name="cacheEnabled" value="true"/><setting name="lazyLoadingEnabled" value="true"/>
</settings>

6.映射器

MapperRegistry:注册绑定我们的Mapper文件;

<!--    每一个Mapper.xml需要在mybatis核心配置文件中注册--><mappers><mapper resource="com/kuang/dao/UserMapper.xml"/></mappers>
  • 接口和它的Mapper配置文件必须同名。
  • 接口和它的Mapper配置文件必须在同一个包下。

7.声明周期和作用域

SqlSessionFactoryBuilder:

  • 一旦创建了SqlSessionFactory,就不再需要它了。
  • 局部变量

SqlSessionFactory:

  • 可以想象为:数据库连接池
  • SqlSessionFactory一旦被创建就应该在运行期间一直存在,没有任何理由丢弃它或重新创建另外一个实例。
  • 因此SqlSessionFactory的最佳作用域是应用作用域。
  • 最简单的就是使用单例模式或静态单例模式。

SqlSession:

  • 连接到连接池的一个请求。
  • SqlSesssion的实例不是线程安全的,因此是不能被共享,所以它的最佳作用域是请求或方法作用域。
  • 用完之后需要赶紧关闭,否则资源被占用。

五.解决属性名和列名不一致的问题

数据库中的字段名:

id name pwd

实体类属性:

public class User {private int id;private String name;private String password;
}

出现的问题:User{id=1, name='李白', password='null'}

方法一:起别名

select id,name,pwd as password from mybatis.user

方法二:resultMap

 <resultMap id="UserMap" type="pojo.User"><result column="id" property="id"></result><result column="name" property="name"></result><result column="pwd" property="password"></result></resultMap><select id="getListById" parameterType="int" resultMap="UserMap">select * from mybatis.user where id=#{id}</select>

六.日志

1.日志工厂

如果一个数据库操作,出现了异常,我们需要排错。日志就是最好的助手

logImpl:指定mybatis所用日志的具体实现,未指定时自动查找。

在Mybatis中具体使用哪个- -日志实现,在设置中设定!

常用的有:

SLF4J

LOG4J [掌握]

L0G4J2

JDK_ LOGGING

COMMONS_ LOGGING

STDOUT_ LOGGING [掌握]

NO LOGGING

在mybatis核心配置文件中,配置日志

 <settings><setting name="logImpl" value="STDOUT_LOGGING"/></settings>

2.Log4j

(1)什么是Log4j

.Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、

.我们也可以控制每一条日志的输出格式.

通过定义每-条日志信息的级别,我们能够更加细致地控制日志的生成过程。

通过一个配置文件来灵活地进行配置,而不需要修改应用的代码

(2)导入log4j包

<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency>

(3) log4j.properties

将等级为DEBUG的日志信息,输出到console file这两个目的地。 log4j.rootLogger=DEBUG,console,file

(4) .配置log4j为日志的实现

<settings> <setting name="logImpl" value="LOG4J"/> </settings>

七. 分页

1.使用limmit技术进行分页

SELECT * from user limit startIndex ,pagesize;

作用:减少数据的处理量

(1)接口

List<User> getListByLimit(Map<String,Integer> map);

(2)Mapper.xml

 <select id="getListByLimit" parameterType="map" resultType="pojo.User">select * from mybatis.user limit #{indexStart},#{pagaSize}</select>

(3)测试

 @Testpublic void test(){//第一步获取sqlsessionSqlSession sqlSession = MybatisUtil.getSqlSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);HashMap<String,Integer> map = new HashMap<>();map.put("indexStart",0);map.put("pagaSize",2);List<User> users=userMapper.getListByLimit(map);System.out.println(users);}

2.RowBounds分页

1.接口

 List<User> getUSerByRowBounds();

2.Mapper.xml

<select id="getUSerByRowBounds" resultType="pojo.User">select * from mybatis.user</select>

3.测试

@Testpublic void test(){//第一步获取sqlsessionSqlSession sqlSession = MybatisUtil.getSqlSession();
//        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);RowBounds rowBounds = new RowBounds(1,1);List<User> users=sqlSession.selectList("dao.UserMapper.getUSerByRowBounds",null,rowBounds);for (User user : users){System.out.println(user);}sqlSession.close();}
}

八.使用注解开发

本质:反射机制实现
底层:动态代理

Mybatis详细执行流程:

UserMapper中的接口上编写sql注解:

public interface UserMapper {@Select("select * from user")List<User> getUserList();
}

核心配置文件mybatis-config.xml中绑定接口:

 <!--    绑定接口--><mappers><mapper class="com.kuang.dao.UserMapper"></mapper></mappers>

测试:

 @Testpublic void getUserList(){SqlSession sqlSession = MybatisUtils.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);List<User> userList = mapper.getUserList();for (User user : userList) {System.out.println(user);}sqlSession.close();}

注解增删改查:

1. 更改Mybatis工具类,设置为自动提交事务。

 public static SqlSession getSqlSession(){//设置为自动提交事务return sqlSessionFactory.openSession(true);}

2. 编写接口增加注解:

法存在多个参数的时候,所有的参数前面必须加上@Param("id")注解@Select("select * from user where id = #{id}")User getUserById(@Param("id") int id);//引用型对象则不需要Param@Insert("insert into user(id,name,pwd) values(#{id},#{name},#{password})")int addUser(User user);@Update("update user set name=#{name},pwd=#{password} where id = #{id}")int updateUser(User user);@Delete("delete from user where id = #{uid}")int deleteUser(@Param("uid") int id);

关于@Param()注解:

  • 基本类型的参数或者String类型,需要加上。
  • 引用类型不需要加。
  • 如果只有一个基本类型的话,可以忽略,但是建议都加上。
  • 在SQL中引用的就是Param()中设定的属性名,可以自定义

九.Lombok

1. 在IDEA中安装Lombok插件

2. 在pom.xml文件中添加依赖

        <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.10</version></dependency>

3. 在实体类上加注解即可

@Date:无参构造,get set toString hashCode equals
@AllArgsConstructor  有参构造
@NoArgsConstructor   无参构造
@EqualsAndHashCode
@ToString
@Getter
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private int id;private String name;private String password;
}

十.复杂查询

1.多对一处理

(1)复杂环境搭建

1.导入lombok

2. 新建实体类Teacher,Student

@Data
public class Teacher {private int id;private String name;
}
@Data
public class Student {private int id;private String name;private Teacher teacher;
}

3. 建立Mapper接口

public interface TeacherMapper {@Select("select * from teacher where id = #{tid}")Teacher getTeacher(@Param("tid") int id);
}
public interface StudentMapper {
}

4. 建立TeacherMapper.xml、StudentMapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.kuang.dao.StudentMapper"></mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.kuang.dao.TeacherMapper"></mapper>

5. 在核心配置文件中绑定注册Mapper接口或者文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--    引入外部配置文件--><properties resource="db.properties"><property name="username" value="root"/><property name="password" value="11111"/></properties><!--    日志工厂--><settings><setting name="logImpl" value="STDOUT_LOGGING"/></settings><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 class="com.kuang.dao.TeacherMapper"/><mapper class="com.kuang.dao.StudentMapper"/></mappers></configuration>

6. 测试查询是否能够成功

    @Testpublic void test(){ //根据id查询老师SqlSession sqlSession = MybatisUtils.getSqlSession();TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);Teacher teacher = mapper.getTeacher(1);System.out.println(teacher);sqlSession.close();}

按照结果嵌套处理

<!--    按照结果嵌套处理--><select id="getStudent2" resultMap="StudentTeacher2">select s.id sid, s.name sname,t.name tnamefrom student s,teacher twhere s.tid = t.tid</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"/></association></resultMap>

按照查询嵌套处理

StudentMapper.xml文件配置

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.kuang.dao.StudentMapper"><!--    思路:1.查询所有的学生信息2.根据查询出来的学生的tid,需找对应的老师。  类似子查询
--><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   集合:collection  --><association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/></resultMap><select id="getTeacher" resultType="Teacher">select * from teacher where id = #{id}</select></mapper>

2.一对多处理

比如:一个老师拥有多个学生,对老师而言,就是一对多的关系。

实体类:

@Data
public class Teacher {private int id;private String name;private List<Student> student;
}
@Data
public class Student {private int id;private String name;private int tid;
}

按照结果嵌套处理

<!--    按结果嵌套查询--><select id="getTeacher" resultMap="TeacherStudent">select s.id sid, s.name sname, t.name tname, t.id tidfrom student s,teacher twhere s.tid = t.id and t.id = #{tid}</select><resultMap id="TeacherStudent" type="Teacher"><result property="id" column="tid"/><result property="name" column="tname"/>
<!--        Teacher类中有List类型的属性,javaType:指定属性的类型。集合中的泛型信息,使用ofType获取--><collection property="student" ofType="Student"><result property="id" column="sid"/><result property="name" column="sname"/><result property="tid" column="tid"/></collection></resultMap>

按照查询嵌套处理

    <select id="getTeacher2" resultMap="TeacherStudent2">select * from mybatis.teacher where id = #{tid}</select><resultMap id="TeacherStudent2" type="Teacher"><collection property="student" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/></resultMap><select id="getStudentByTeacherId" resultType="Student">select * from mybatis.student where tid = #{tid}</select>

十一.动态SQL

动态SQL:就是根据不同的条件生成不同的SQL语句。

动态SQL就是在拼接SQL语句,只需要保证SQL的正确性,按照SQL的格式,进行排列组合即可。

搭建环境

CREATE TABLE `blog`(
`id` VARCHAR(50) NOT NULL COMMENT '博客id',
`title` VARCHAR(100) NOT NULL COMMENT '博客标题',
`author` VARCHAR(30) NOT NULL COMMENT '博客作者',
`create_time` DATETIME NOT NULL COMMENT '创建时间',
`views` INT(30) NOT NULL COMMENT '浏览量'
)ENGINE=INNODB DEFAULT CHARSET=utf8;

创建一个基础工程

  1. 导包
  2. 编写配置文件
  3. 编写实体类
@Data
public class Blog {private int id;private String title;private String author;private Date createTime; //需解决实体类属性和数据库字段不一致private int views;
}

4.编写实体类对应的Mapper接口和Mapper.xml文件

public interface BlogMapper {//插入数据int addBlog(Blog blog);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.kuang.dao.BlogMapper"><insert id="addBlog" parameterType="blog">insert into mybatis.blog(id,title,author,create_time,views)values (#{id},#{title},#{author},#{createTime},#{views});</insert>
</mapper>
  1. 5.随机数生成工具类 (utils.IDUtils)
public class IDUtils {public static String getId(){return UUID.randomUUID().toString().replaceAll("-","");}@Testpublic void test(){System.out.println(IDUtils.getId());}
}

6.插入Blog数据

    @Testpublic void addInitBlog(){SqlSession sqlSession = MybatisUtils.getSqlSession();BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);Blog blog = new Blog();blog.setId(IDUtils.getId());//随机的数blog.setTitle("Mybatis如此简单");blog.setAuthor("狂神说");blog.setCreateTime(new Date());blog.setViews(999);mapper.addBlog(blog);blog.setId(IDUtils.getId());blog.setTitle("Java如此简单");mapper.addBlog(blog);blog.setId(IDUtils.getId());blog.setTitle("Spring如此简单");mapper.addBlog(blog);blog.setId(IDUtils.getId());blog.setTitle("微服务");mapper.addBlog(blog);sqlSession.close();}

IF语句

1. Blog接口

public interface BlogMapper {//插入数据int addBlog(Blog blog);//查询博客List<Blog> queryBlogIf(Map map);
}

2. BlogMapper.xml文件

根据条件查询,如果没有条件要求,输出所有的数据。否则,按照输入的要求条件输出。

    <select id="queryBlogIf" parameterType="map" resultMap="UserBlog">select * from mybatis.blog where 1=1<if test="title != null">and title = #{title}</if><if test="author != null">and author = #{author}</if></select><!--    结果集映射,解决数据库字段和实体类属性名字不一致问题--><resultMap id="UserBlog" type="Blog"><result column="create_time" property="createTime"/></resultMap>

3. 测试类

    @Testpublic void queryBlogIf(){SqlSession sqlSession = MybatisUtils.getSqlSession();BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);HashMap map = new HashMap();
//        map.put("title","Java如此简单");map.put("author","狂神说");List<Blog> blogs = mapper.queryBlogIf(map);for (Blog blog : blogs) {System.out.println(blog);}}

Choose语句

Choose:类似switch结构。从上至下判断,满足其中一个条件,自动跳出。上面都不满足,自动执行otherwise语句中的内容。

    <select id="queryBlogChoose" parameterType="map" resultType="blog">select * from mybatis.blog<where><choose><when test="title!=null">title = #{title};</when><when test="author!=null">and author = #{author}</when><otherwise>and views = #{views}</otherwise></choose></where></select>

trim(Where,set)

Where
Where:条件的追加,IF语句的高级版本。若语句开头为 ”And“ 或 ”OR“,将自动去除。

        <select id="queryBlogIf" parameterType="map" resultMap="UserBlog">select * from mybatis.blog<where><if test="title != null">and title = #{title}</if><if test="author != null">and author = #{author}</if></where></select>

Set

    <update id="updateBlog" parameterType="map">update mybatis.blog<set><if test="title != null">title = #{title},</if><if test="author != null">author = #{author}</if></set>where id = #{id}</update>

所谓的动态SQL,本质还是SQL语句,只是在SQL层面,去执行一个逻辑代码。

SQL片段

实现公用代码的复用,对多sql语句共有的语句进行抽取封装。

  1. 使用SQL标签抽取公共的部分
<!--    sql片段--><sql id="if-title-author"><if test="title != null">and title = #{title}</if><if test="author != null">and author = #{author}</if></sql>

2.在需要使用的地方使用include标签引用即可

    <select id="queryBlogIf" parameterType="map" resultMap="UserBlog">select * from mybatis.blog<where><include refid="if-title-author"></include></where></select>

注意事项:

  • 最好基于单表来定义SQL片段。
  • 不要存在where标签。
  • SQL片段内一般只是IF判断

Foreach

open:以…开头
close:以…结尾
seperator:以…分割

select * from mybatis.blog WHERE ( id = ? or id = ? or id = ? )    <select id="queryBlogForeach" parameterType="map" resultType="blog">select * from mybatis.blog<where><foreach collection="ids" item="id" open="(" close=")" separator="or">id = #{id}</foreach></where></select>

测试类:

    @Testpublic void queryBlogForeach(){SqlSession sqlSession = MybatisUtils.getSqlSession();BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);HashMap map = new HashMap();ArrayList<Integer> ids = new ArrayList();ids.add(1);ids.add(2);ids.add(3);map.put("ids",ids);List<Blog> blogs = mapper.queryBlogForeach(map);for (Blog blog : blogs) {System.out.println(blog);}}

12.缓存

1.简介

1.1什么是缓存?

  • 存在内存中的临时数据。
  • 将用户经常查询的数据放在缓存(内存)中,用户查询时不需从磁盘上查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。

1.2. 为什么使用缓存?

  • 减少和数据库的交互次数,减少系统开销,提高系统效率。

1.3. 什么样的数据使用缓存?

  • 经常查询并且不经常改变的数据。

2. Mybatis缓存

Mybatis系统中默认定义了两级缓存:一级缓存 和 二级缓存

  • 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)
  • 二级缓存需要手动开启和配置,是基于namespace级别的缓存。
  • 为了提高扩展性,Mybatis定义了缓存接口Cache,可通过Cache接口自定义二级缓存。

3.一级缓存

一级缓存也叫本地缓存:

与数据库同一次会话期间查询到的数据会放在本地缓存中。

以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库;

3.1测试

(1) 在mybatis中加入日志,方便测试结果 。

(2)     编写接口方法

//根据id查询用户
User queryUserById(@Param("id") int id);

(3)Mapper.xml

(3) 接口对应的Mapper文件
<select id="queryUserById" resultType="user">select * from user where id = #{id}
</select>

(4)测试

@Test
public void testQueryUserById(){SqlSession session = MybatisUtils.getSession();UserMapper mapper = session.getMapper(UserMapper.class);User user = mapper.queryUserById(1);System.out.println(user);User user2 = mapper.queryUserById(1);System.out.println(user2);System.out.println(user==user2);session.close();
}

(5)结果分析

==>  Preparing: select * from mybatis.user where id=?
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 李白, 静夜思
<==      Total: 1
User{id=1, name='李白', pwd='静夜思'}

4缓存失效

一级缓存是SqlSession级别的缓存,是一直开启的,我们关闭不了它;

一级缓存失效情况:没有使用到当前的一级缓存,效果就是,还需要再向数据库中发起一次查询请求。

(1)sqlSession不同,查询条件相同

public class UserMapperTest {@Testpublic void test(){//第一步获取sqlsessionSqlSession sqlSession1 = MybatisUtil.getSqlSession();SqlSession sqlSession2 = MybatisUtil.getSqlSession();UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);User user=userMapper1.getListById(1);System.out.println(user);User user2=userMapper2.getListById(1);System.out.println(user);}
}

结果分析:

.发送了两条Sql语句
.结论:每个sqlSession中的缓存相互独立

(2) sqlSession相同,查询条件不同

@Testpublic void test(){//第一步获取sqlsessionSqlSession sqlSession = MybatisUtil.getSqlSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);User user=userMapper.getListById(1);System.out.println(user);User user1=userMapper2.getListById(2);System.out.println(user1);}

结果观察:

==>  Preparing: select * from mybatis.user where id=? 
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 李白, 静夜思
<==      Total: 1
User{id=1, name='李白', pwd='静夜思'}
==>  Preparing: select * from mybatis.user where id=? 
==> Parameters: 2(Integer)
<==    Columns: id, name, pwd
<==        Row: 2, 手鞠, 123456
<==      Total: 1
User{id=2, name='手鞠', pwd='123456'}

分析:
日志中发送了两条sql;
因为当前缓存中不存在这个数据

(3) sqlSession相同,两次查询之间执行了增删改操作。

@Testpublic void test(){//第一步获取sqlsessionSqlSession sqlSession = MybatisUtil.getSqlSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);User user=userMapper.getListById(1);System.out.println(user);userMapper.updateUser(new User(1,"杜甫","登高"));User user1=userMapper.getListById(1);System.out.println(user1);}

结果观察:

结果观察:
==>  Preparing: select * from mybatis.user where id=?
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 李白, 静夜思
<==      Total: 1
User{id=1, name='李白', pwd='静夜思'}
==>  Preparing: update mybatis.user set name =?,pwd=? where id=?
==> Parameters: 杜甫(String), 登高(String), 1(Integer)
<==    Updates: 1
==>  Preparing: select * from mybatis.user where id=?
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 杜甫, 登高
<==      Total: 1
User{id=1, name='杜甫', pwd='登高'}

分析:

分析:
因为增删改会改变数据,所以执行了两次。

(4) sqlSession相同,手动清除一级缓存

(4) sqlSession相同,手动清除一级缓存 @Testpublic void test(){//第一步获取sqlsessionSqlSession sqlSession = MybatisUtil.getSqlSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);User user=userMapper.getListById(1);System.out.println(user);sqlSession.clearCache();userMapper.updateUser(new User(1,"杜甫","登高"));User user1=userMapper.getListById(1);System.out.println(user1);}

结果观察:

==>  Preparing: select * from mybatis.user where id=?
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 李白, 静夜思
<==      Total: 1
User{id=1, name='李白', pwd='静夜思'}
==>  Preparing: update mybatis.user set name =?,pwd=? where id=?
==> Parameters: 杜甫(String), 登高(String), 1(Integer)
<==    Updates: 1
==>  Preparing: select * from mybatis.user where id=?
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 杜甫, 登高
<==      Total: 1
User{id=1, name='杜甫', pwd='登高'}

5.二级缓存

1.概念

二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
基于namespace级别的缓存,一个名称空间,对应一个二级缓存;

2.工作机制

.一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
.如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中;
.新的会话查询信息,就可以从二级缓存中获取内容;
.不同的mapper查出的数据会放在自己对应的缓存(map)中;

(1)开启全局缓存

<setting name="cacheEnabled" value="true"/>

(2) 去每个mapper.xml中配置使用二级缓存

<cacheeviction="FIFO"flushInterval="60000"size="512"readOnly="true"/>

这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。

测试:

@Testpublic void test(){//第一步获取sqlsessionSqlSession sqlSession = MybatisUtil.getSqlSession();SqlSession sqlSession1 = MybatisUtil.getSqlSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);User user=userMapper.getListById(1);System.out.println(user);sqlSession.close();User user1=userMapper1.getListById(1);System.out.println(user1);System.out.println(user==user1);sqlSession1.close();}

只要开启了二级缓存,我们在同一个Mapper中的查询,可以在二级缓存中拿到数据

查出的数据都会被默认先放在一级缓存中

只有会话提交或者关闭以后,一级缓存中的数据才会转到二级缓存中

Mybatis知识整理相关推荐

  1. 一:MyBatis知识整理(1)

    一:MyBatis的架构 1.mybatis配置SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息.mapper.xml文件即sql映射文件 ...

  2. *Java软件开发面试知识整理*

    Java软件开发面试知识整理 围绕以下几点回答问题:是什么.为什么.什么时候用.项目实现.解决什么问题.遇到的困难 谈谈你对Java和C的理解? Java: 面向对象.Unicode:可以跨平台(JV ...

  3. python常用变量名_python基础知识整理

    Python Python开发 Python语言 python基础知识整理 序言:本文简单介绍python基础知识的一些重要知识点,用于总结复习,每个知识点的具体用法会在后面的博客中一一补充程序: 一 ...

  4. Spring AOP 知识整理

    为什么80%的码农都做不了架构师?>>>    AOP知识整理 面向切面编程(AOP)通过提供另外一种思考程序结构的途经来弥补面向对象编程(OOP)的不足.在OOP中模块化的关键单元 ...

  5. Linux系统基础知识整理

    一.说明 本篇文章,我将结合自己的实践以及简介,来对linux系统做一个直观清晰的介绍,使得哪些刚接触Linux的小伙伴可以快速入门,也方便自己以后进行复习查阅. 二.基本知识整理 1.Linux文件 ...

  6. 计算机二级c语基础知识,计算机二级C语基础知识整理.doc

    计算机二级C语基础知识整理 1.1 算法 算法:是一组有穷指令集,是解题方案的准确而完整的描述.通俗地说,算法就是计算机解题的过程.算法不等于程序,也不等于计算方法,程序的编制不可能优于算法的设计. ...

  7. js事件(Event)知识整理

    鼠标事件 鼠标移动到目标元素上的那一刻,首先触发mouseover  之后如果光标继续在元素上移动,则不断触发mousemove  如果按下鼠标上的设备(左键,右键,滚轮--),则触发mousedow ...

  8. Spring学习篇:IoC知识整理(一)

    现在正通过spring的官方文档学习spring,将自己学习时的点点滴滴记录下来. Ioc知识整理(一): IoC (Inversion of Control) 控制反转. 1.bean的别名 我们每 ...

  9. 使用Aspose.Cells的基础知识整理

    使用Aspose.Cells的基础知识整理 转自 http://www.cnblogs.com/kenblove/archive/2009/01/07/1371104.html 这两天用Aspose. ...

最新文章

  1. C++中插件使用举例
  2. Jenkins_获取源码编译并启动服务(二)
  3. 香肠派对电脑版_香肠派对2020先行服最新内测版(众神降临)-香肠派对2020先行服游戏下载v9.82...
  4. 前亚马逊中国总裁王汉华出任好耶CEO
  5. linux下移动或者复制文件覆盖相同文件夹时,文件夹里面的每个文件都提示是否覆盖...
  6. BZOJ 3326 [SCOI2013]数数 (数位DP)
  7. 可以检测手机帧率和温度的软件_腾讯黑鲨游戏手机3评测:深度定制带来的全新游戏体验...
  8. 如何在不被支持的termux下载gh
  9. 舞蹈链算法与数独求解
  10. PHICOMM(斐讯)N1盒子 - Armbian5.77(Debian 9)配置自动连接WIFI无线网络
  11. 学生计算机机房管理系统设计
  12. ubuntu repo安装方法
  13. win7系统如何映射服务器,win7系统如何映射网络驱动器 win7系统映射网络驱动器方法...
  14. 自动驾驶数据集下载!检测/分割/车道线/交标/车牌/行人识别等
  15. Java Class
  16. (5) 什么是数据项--每天五分钟学习数据结构
  17. linux设备授权命令,# Linux命令
  18. 一条命令导出电脑中所有wifi账号密码
  19. gradle-6.1.1-all 快速下载
  20. bash: 无法执行二进制文件: 可执行文件格式错误

热门文章

  1. 【Android安全】自带加密光环的SharedPreference
  2. 对抗大脑里的简单思维 ——读《清醒思考的艺术:你最好让别人去犯的52种思维错误》
  3. 正则表达式获取网页文本内容
  4. 【Java高级语法】(十一)枚举类:还在因为使用了魔法数而被老大怼吗,一起来看看枚举器的作用吧!~
  5. 怎样才能画好动漫人物的脸?画好动漫人物的脸有哪些技巧?
  6. vue3 + video + canvas 人脸识别
  7. 【Linux】版本管理工具 Git
  8. 组装电脑基础知识之固态硬盘
  9. 第13周项目3-Dijkstra算法的验证
  10. xshell命令大全