Mybatis知识全解笔记

目录:

     查看知识点请点击跳转!(笔记未写完)
        引言

  1. Mybatis简介
  2. 第一个Mybatis程序       拓展知识:资源过滤
  3. 增删改查的实现
  4. 错误排查指导
  5. Map和模糊查询拓展
  6. 配置之属性优化
  7. 配置之别名优化与setting设置
  8. 配置之映射器说明
  9. 生命周期和作用域
  10. ResultMap映射
  11. 日志工厂
  12. Log4j讲解
  13. Limit实现分页
  14. PowBounds分页
  15. 使用注解开发
  16. Mybatis执行流程剖析
  17. 注解增删改查
  18. Lombok的使用
  19. 复杂查询环境搭建
  20. 多对一的处理
  21. 一对多的处理
  22. 动态SQL环境搭建
  23. 动态SQL之IF语句
  24. 动态SQL之常用标签
  25. 动态SQL之Foreach
  26. 缓存简介
  27. 一级缓存
  28. 二级缓存
  29. Mybatis缓存原理
  30. 自定义缓存Ehcache
  31. Mybatis总结
  32. 聊聊Spring这东西

资料整理来源于网络和b站狂神视频只用于笔记学习,如有侵权,请联系作者删除或者指明来源链接。

返回目录
引言:开始之前我大致学习了JDBC来操作数据库(JDBC:
https://blog.csdn.net/m0_57249797/article/details/118392897
)然后数据库sql语句必须掌握(mysql:https://blog.csdn.net/m0_57249797/article/details/118392963
比较:使用Mybatis与JDBC哪个更有优势

  • Mybatis框架也是在JDBC上封装了一层,底层也是JDBC原理。
  • 直接写JDBC代码的效率确实高,但是纯用JDBC,只要项目达到一定规模,那我们项目里的代码量就会非常多;最重要的是,很多代码都是重复的;如果我们项目里边积累了很多重复的代码,最致命的问题就是不好维护
  • 我听说过的运用持久化层的技术:JDBC/DBUtils/Spring JDBCTemplate/Hibernate/Mybatis
  • 入门:使用Mybatis的步骤
    1.引入pom依赖
    2.Mybatis的配置文件
    3.编写映射文件
    4.得到sqlsession执行语句
    5.关闭session

正式开始

根据b站狂神视频整理的笔记

Mybatis-9.28

环境:

  • JDK1.8
  • Mysql
  • Maven
  • IDEA

回顾:

SSM框架:配置文件的。最好的方式:看官网文档(Mybatis3中文文档,最新链接:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html);

1.简介

返回目录

1.1什么是Mybatis

在这里插入图片描述

  • MyBatis 是一款优秀的持久层框架
  • 它支持自定义 SQL、存储过程以及高级映射。
  • MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
  • MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
  • MyBatis 本是apache的一个开源项目iBatis(iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)), 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。
  • 2013年11月迁移到Github。

如何获得Mybatis?

  • Maven仓库(个人建议)
<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis</artifactId>
	<version>3.5.2</version>
</dependency>
  • Github
  • 中文文档
1.2 持久层

数据持久化

  • 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
  • 内存:断电即失
  • 数据库(jdbc),io文件持久化
  • 生活:冷藏,罐头
    为什么需要持久化
  • 有一些对象不能让它丢掉
  • 内存太贵了
1.3 持久层

Dao层,Service层,Controller层…

  • 完成持久化工作的代码块
  • 层界限十分明显
1.4 为什么需要Mybatis
  • 帮助程序员将数据存入到数据库中
  • 方便
  • 传统的JDBC代码太复杂了。简化。框架。自动化。
  • 不用Mybatis也可以,用它更容易上手。技术没有高低之分
  • 优点:
    1.简单易学
    2.灵活
    3.SQL和代码分离,提高了可维护性
    4.提供映射(什么叫映射?是map/mapper直译过来的意思,就是汉语表达map/mapper)标签,支持对象与数据库的orm字段关系映射
    5.提供对象关系映射标签,支持对象关系组建维护
    6.提供xml标签,支持编写动态sql。

最重要的一点:使用的人多!!!

2.第一个Mybatis程序

返回目录
思路:搭建环境–>导入Mybatis–>编写代码–>测试

2.1搭建环境

搭建数据库
在这里插入图片描述
新建项目

  1. 新建一个普通的Maven项目
  2. 删除src目录
  3. 导入Maven依赖
 <!--导入依赖-->
    <dependencies>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <!--Mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>

        <!--Junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

    </dependencies>
2.2 创建一个模块
  • 编写mybatis的核心配置文件(我把时区设置为北京时间东八区)
<?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核心配置文件-->
<configuration>

    <environments default="development">
        <environment id="development">
<!--   transactionManager事务管理         -->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!--useSSL=true&amp;有问题-->
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;character=UTF-8&amp;serverTimezone=GMT%2B8"/>
                <property name="username" value="root"/>
                <property name="password" value="198810"/>
            </dataSource>
        </environment>
    </environments>
<!--每一个Mapper.xml都需要在Mybatis核心配置文件中注册-->
    <mappers>
        <mapper resource="com/kuang/dao/UserMapper.xml"/>
<!--        <mapper class="com.kuang.dao.UserDao"/>-->
<!--        <package name="com.kuang.dao"/>-->
    </mappers>
</configuration>
  • 编写mybatis工具类
//sqlSessionFactory-->sqlSession
public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            //使用Mybatis第一步:获取sqlSessionFactory对象
            String resource = "mybatis-config.xml";
            InputStream  inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//    既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
//    SqlSession 提供了在数据库执行 SQL 命令所需的所有方法(完全包含了面向数据库执行SQL命令所需的所有方法)
    public static SqlSession getSqlSession(){
        SqlSession sqlSession = sqlSessionFactory.openSession();//Ctrl+Alt+V补全对象创建
        return sqlSession;
    }
    //至此可以对比JDBC完成connection对象创建,可以连接上数据库了。
}
2.3编写代码
  • 实体类
package com.kuang.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;
    }
}
  • Dao接口
public interface UserDao {//等价于Mapper

    List<User> getUserList();
    
}
  • 接口实现类由原来UserDaoImpI转变为一个Mapper配置文件.
<?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绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.kuang.dao.UserDao">
    <!--select是查询语句标签-->
    <!--记住两个常用的返回类型resultType和resultMap-->
    <select id="getUserList" resultType="com.kuang.pojo.User">
    select * from mybatis.user;//查询mybatis数据库下的user表中所有数据
    </select>
</mapper>

2.4测试

资源过滤:

返回目录
在初学mybatis中,经常会报一个异常:

Caused by: org.apache.ibatis.exceptions.PersistenceException: 
### Error building SqlSession.
### The error may exist in com/Adu/mapper/UserMapper.xml
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource com/Adu/mapper/UserMapper.xml
	at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)

原因:有时候IDEA不会加载除’.class’文件,所以我们要配置在pom.xml(最好所有)配置文件中加入(约定大于配置):

<build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>

MapperRegistry是什么?
核心配置文件注册mappers

  • junit测试
public class UserDaoTest {
    @Test
    public void set(){
        //第一步:获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //执行SQL
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        List<User> userList = userDao.getUserList();
        for(User user:userList){
            System.out.println(user);
        }
        //关闭SqlSession
        sqlSession.close();
    }
}
  • 可能遇到的问题:
    1.配置文件没有注册
    2.绑定接口错误
    3.方法名不对
    4.返回类型不对
    5.Maven导出资源问题

学完后展示一下目录结构:
在这里插入图片描述
我个人还遇到了SSL连接问题。尚未解决

以下是b站狂神视频目录,逐步写成笔记

3.增删改查的实现(CRUD)

返回目录
1.namespace

  • 将上面案例中的UserMapper接口改名为 UserDao;
  • 将UserMapper.xml中的namespace改为为UserDao的路径 .
  • 再次测试

配置文件中namespace中的名称为对应Mapper接口或者Dao接口的完整包名,必须一致!
在这里插入图片描述
在这里插入图片描述
注意点:增、删、改操作需要提交事务!
在这里插入图片描述
在这里插入图片描述

2.实现增删改查的接口方法

    //根据ID查询用户
    User getUserById(int id);
    //insert一个用户
    int addUser(User user);
    //修改用户
    int updateUser(User user);
    //删除用户
    int deleteUser(int id);
    //建议写法:int deleteUser(@Param("id") int id);//@Param("id") 在只有一个参数的情况下可以省略

3.xml的映射配置文件

    <select id="getUserById" parameterType="int" resultType="com.kuang.pojo.User">
        select * from mybatis.user where id=#{id};
    </select>
    
    <insert id="addUser" parameterType="com.kuang.pojo.User">
        insert into mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd});
    </insert>
    
    <update id="updateUser" parameterType="com.kuang.pojo.User">
        update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id};
    </update>
    
    <delete id="deleteUser" parameterType="int">
        delete from mybatis.user where id=#{id};
    </delete>

3.测试方法

	//CRUD
	@Test
	public void getUserById(){
    //第一步:获取SqlSession对象
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    //执行SQL
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user=mapper.getUserById(1);
	//System.out.println(userList.get(0).getName());
    System.out.println(user);
    //关闭SqlSession
    sqlSession.close();
    }
    @Test
    public void addUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //执行SQL
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.addUser(new User(4,"t","123"));
        sqlSession.commit();
        sqlSession.close();
    }
    @Test
    public void updateUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //执行SQL
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.updateUser(new User(4,"你","1223"));
        sqlSession.commit();
        sqlSession.close();
    }
    @Test
    public void deleteUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //执行SQL
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        System.out.println( mapper.deleteUser(4));
        sqlSession.commit();
        sqlSession.close(); mapper.deleteUser(4);
    }

要点:

  • 所有的增删改操作都需要提交事务!
  • 接口所有的普通参数,尽量都写上@Param参数,尤其是多个参数时,必须写上!
  • 有时候根据业务的需求,可以考虑使用map传递参数!(后面介绍)
  • 为了规范操作,在SQL的配置文件中,我们尽量将Parameter参数和resultType都写上!

4.错误排查指导

返回目录

  • 标签不要匹配错
  • resource绑定mapper,需要使用路径
  • 程序配置文件必须符合规范
  • NullPointerException,没有注册到资源
  • 输出的xml文件存在中文乱码问题
  • Maven资源没有导出问题

5.Map和模糊查询拓展

返回目录
课堂练习:根据 密码 和 名字 查询用户

思路一:直接在方法中传递参数
1、在接口方法的参数前加 @Param属性
2、Sql语句编写的时候,直接取@Param中设置的值即可,不需要单独设置参数类型

//通过密码和名字查询用户
User selectUserByNP(@Param("username") String username,@Param("pwd") String pwd);

/*
   <select id="selectUserByNP" resultType="com.kuang.pojo.User">
     select * from user where name = #{username} and pwd = #{pwd}
   </select>
*/

思路二:使用万能的Map

1、在接口方法中,参数直接传递Map;

User selectUserByNP2(Map<String,Object> map);

2、编写sql语句的时候,需要传递参数类型,参数类型为map

<select id="selectUserByNP2" parameterType="map" resultType="com.kuang.pojo.User">
select * from user where name = #{username} and pwd = #{pwd}
</select>

3、在使用方法的时候,Map的 key 为 sql中取的值即可,没有顺序要求!

Map<String, Object> map = new HashMap<String, Object>();
map.put("username","小明");
map.put("pwd","123456");
User user = mapper.selectUserByNP2(map);

总结:如果参数过多,我们可以考虑直接使用Map实现,如果参数比较少,直接传递参数即可
模糊查询like语句该怎么写?
第1种:在Java代码中添加sql通配符。
UserMapper接口中添加方法:

List<User> selectlike(String value);

映射文件中配置:

    <select id="selectlike" resultType="com.kuang.pojo.User">
    select * from user where name like #{value}
    </select>

测试代码:

 public void test02(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //执行SQL
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        String wildcardname = "%李%";
        List<User> names = mapper.selectlike(wildcardname);
        for (User name : names) {
            System.out.println(name);
        }
        sqlSession.close();
    }

结果:
在这里插入图片描述

第2种:在sql语句中拼接通配符,会引起sql注入
映射文件改变:

<select id="selectlike" resultType="com.kuang.pojo.User">
    select * from user where name like "%"#{value}"%";
</select>

6.配置之属性优化

返回目录
在这里插入图片描述
解析引入:

<?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核心配置文件-->
<configuration>

    <environments default="development"><!--default为默认使用哪个数据库环境的id属性名-->
        <!--下面为我的第一套数据库,id为环境名-->
        <environment id="development"><!--id为环境名-->
<!--   transactionManager事务管理         -->
            <transactionManager type="JDBC"/><!--事务管理器-->
            <dataSource type="POOLED"><!--数据源(常见:c3p0和DBCP、druid)-->
                <!--我们可以设置property属性来实现配置文件-->
    <!--这些属性都是可以外部配置且可以动态替换的,既可以在典型的java属性文件中配置,亦可通过properties元素的子元素来传递[db.properties]-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!--useSSL=true&amp;有问题-->
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;useSSL=false&amp;character=UTF-8&amp;serverTimezone=GMT%2B8"/>
                <property name="username" value="root"/>
                <property name="password" value="198810"/>
            </dataSource>
        </environment>
        <!--下面为我的第二套数据库,id为环境名-->
        <environment id="sql02">
            <!--   transactionManager事务管理         -->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!--useSSL=true&amp;有问题-->
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;useSSL=false&amp;character=UTF-8&amp;serverTimezone=GMT%2B8"/>
                <property name="username" value="root"/>
                <property name="password" value="198810"/>
            </dataSource>
        </environment>
    </environments>
<!--每一个Mapper.xml都需要在Mybatis核心配置文件中注册-->
    <mappers>
        <mapper resource="com/l/dao/UserMapper.xml"/>
    </mappers>

</configuration>

在这里插入图片描述

注:<transactionManager type=“JDBC”/>下的属性和属性值用不上,可以暂时忽略不写

属性优化(properties)

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

编写一个配置文件:
在resource下建立db.properties并写上如下配置:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&useSSL=false&character=UTF-8&serverTimezone=GMT%2B8
username=root
password=198810

在核心配置文件中引入
(在xml中,所有的标签都可以规定其顺序)

    <properties resource="db.properties"><!--第一步引入外部配置文件-->
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </properties>

完整代码:

<?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"><!--第一步引入外部配置文件-->
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </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/l/dao/UserMapper.xml"/>
    </mappers>

</configuration>

注意点:

  • 可以直接引入外部文件
  • 可以在其中增加一些属性配置
  • 如果两个文件有同一个字段优先使用外部配置文件的

7.配置之别名优化与setting设置

返回目录
在这里插入图片描述
代码:
第一种取别名的方式,指定类:

    <typeAliases>
        <typeAlias type="com.l.pojo.User" alias="User"/>
    </typeAliases>

映射文件:

    <select id="getUserList" resultType="User">
   		 select * from mybatis.user;
    </select>

第二种取别名的方式,指定包(别名就为类名【首字母可大小写,官方建议小写】):

    <typeAliases>
        <package name="com.l.pojo"/>
    </typeAliases>

映射文件:

    <select id="getUserList" resultType="User">
   		 select * from mybatis.user;
    </select>

第三种,在扫描包的情况下,我们也使用@Alias注解来实现其他别名的设置
在这里插入图片描述
映射文件:

    <select id="getUserList" resultType="U">
   		 select * from mybatis.user;
    </select>

setting设置

在这里插入图片描述

8.配置之映射器说明

返回目录
MapperRegistry:注册绑定我们的Mapper文件;
方式一:【推荐使用】

<!-- 使用相对于类路径的资源引用 -->
<!--每一个Mapper.xml都需要在MyBatis核心配置文件中注册-->
    <mappers>
        <mapper resource="com/l/dao/UserMapper.xml"/>
    </mappers>

方式二:
通过类名(属性值配置的是接口名)去注册:

<!--
使用映射器接口实现类的完全限定类名
需要配置文件名称和接口名称一致,并且位于同一目录下
-->
    <mappers>
        <mapper class="com.l.dao.UserMapper"/>
    </mappers>

使用方式二的注意点:

  • 接口和它的Mapper配置文件必须同名
  • 接口和它的Mapper配置文件必须在同一包下

方式三:使用扫描包进行注入绑定

<!--
将包内的映射器接口实现全部注册为映射器
但是需要配置文件名称和接口名称一致,并且位于同一目录下
-->
    <mappers>
        <package name="com.l.dao"/>
    </mappers>

目录结构:
在这里插入图片描述

9.生命周期和作用域

返回目录
在这里插入图片描述
上面的每一个Mapper,就代表一个具体的业务!

10.ResultMap映射

返回目录

解决属性名和字段名不一致的问题

数据库中的字段:
在这里插入图片描述
新建一个项目,拷贝之前的,测试实体类字段不一致的情况

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

映射文件:

    <select id="getUserById" parameterType="int" resultType="com.l.pojo.User">
        select * from mybatis.user where id=#{id};
    </select>

查询结果:
在这里插入图片描述
分析:

  • select * from user where id = #{id} 可以看做
  • select id,name,pwd from user where id = #{id}
  • mybatis会根据这些查询的列名(会将列名转化为小写,数据库不区分大小写) , 去对应的实体类中查找相应列名的set方法设值 , 由于找不到setPwd() , 所以password返回null ; 【自动映射】

解决方案
方案一:为列名指定别名 , 别名和java实体类的属性名一致 .

<select id="selectUserById" resultType="User">
  select id , name , pwd as password from user where id = #{id}
</select>

方案二:使用结果集映射->ResultMap 【推荐】

<resultMap id="UserMap" type="User">
   <!-- id为主键 -->
   <id column="id" property="id"/>
   <!-- column是数据库表的列名 , property是对应实体类的属性名 -->
   <result column="name" property="name"/>
   <result column="pwd" property="password"/>
</resultMap>

<select id="selectUserById" resultMap="UserMap">
  select * from user where id = #{id}
</select>

在这里插入图片描述
在这里插入图片描述

11.日志工厂

返回目录

  1. 思考:我们在测试SQL的时候,要是能够在控制台输出 SQL 的话,是不是就能够有更快的排错效率?
  2. 如果一个数据库操作,出现了异常,我们需要排错。日志就是最好的助手!
  3. 如果一个 数据库相关的操作出现了问题,我们可以根据输出的SQL语句快速排查问题。

曾经:sout、debug
现在日志工厂(对于以往的开发过程,我们会经常使用到debug模式来调节,跟踪我们的代码执行过程。但是现在使用Mybatis是基于接口,配置文件的源代码执行过程。因此,我们必须选择日志工具来作为我们开发,调节程序的工具)
Mybatis内置的日志工厂提供日志功能,具体的日志实现有以下几种工具:

  • SLF4J
  • Apache Commons Logging
  • Log4j 2
  • JDK logging
  • Log4j【掌握】
  • STDOUT_LOGGING【掌握】

具体选择哪个日志实现工具由MyBatis的内置日志工厂确定。它会使用最先找到的(按上文列举的顺序查找)。如果一个都未找到,日志功能就会被禁用。

STDOUT_LOGGING标准日志输出
在核心配置文件中配置日志:

    <settings>
   		<!--标准的日志工厂实现-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

运行测试输出日志结果:
在这里插入图片描述

12.Log4j讲解

返回目录
简介:

  • Log4j是Apache的一个开源项目
  • 通过使用Log4j,我们可以控制日志信息输送的目的地:控制台,文本,GUI组件…
  • 我们也可以控制每一条日志的输出格式;
  • 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
    使用步骤:
    1、导入log4j的包
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

2、配置文件编写(在resource下建立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/kuang.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

运行查询代码
结果:
在这里插入图片描述
简单使用:
1.在要使用Log4j的类中,导入包 import org.apache.log4j.Logger;
2.日志对象,参数为当前类的class,范围为全局变量

static Logger logger = Logger.getLogger(UserDaoTest.class);

3.日志级别

   logger.info("info:进入getUserById方法");
   logger.debug("debug:进入getUserById方法");
   logger.error("error: 进入getUserById方法");

4.测试代码:

    public void test() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        logger.info("info:进入getUserById方法成功");
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        logger.debug("debug:进入getUserById方法");
        User user = mapper.getUserById(1);
        logger.error("error: 进入getUserById方法");
        System.out.println(user);
        sqlSession.close();
    }

结果:
在这里插入图片描述
可以看到还生成了一个日志的文件 【需要修改file的日志级别】

13.Limit实现分页

返回目录

思考:为什么需要分页?

  • 减少数据的处理量

在学习mybatis等持久层框架的时候,会经常对数据进行增删改查操作,使用最多的是对数据库进行查询操作,如果查询大量数据的时候,我们往往使用分页进行查询,也就是每次处理小部分数据,这样对数据库压力就在可控范围内。
使用Limit实现分页
普通sql语句查询语法:

#语法
SELECT * FROM table LIMIT stratIndex,pageSize
#操作
SELECT * FROM table LIMIT 5,10; // 检索记录行 6-15  
#如果只给定一个参数,它表示返回最大的记录行数目:   
SELECT * FROM table LIMIT 5; //检索前 5 个记录行 
#换句话说,LIMIT n 等价于 LIMIT 0,n。 

在这里插入图片描述
在这里插入图片描述
mybatis实现分页查询:
步骤:
1、修改映射文件:

<select id="selectUser" parameterType="map" resultType="user">
  select * from user limit #{startIndex},#{pageSize}
</select>

2、接口中增加方法,参数为map(建议多使用万能的map)

//选择全部用户实现分页
List<User> selectUser(Map<String,Integer> map);

3、在测试类中传入参数测试

  • 推断:起始位置 = (当前页面 - 1 ) * 页面大小
    @Test
    public void test02() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        Map<String,Integer> map=new HashMap<String, Integer>();
        map.put("startIndex",0);
        map.put("pageSize",3);
        List<User> user = mapper.SelectUser(map);
        for (User user1 : user) {
            System.out.println(user1);
        }
        sqlSession.close();
    }

结果:
在这里插入图片描述

14.PowBounds分页

返回目录
我们除了使用Limit在SQL层面实现分页,也可以使用RowBounds在Java代码层面实现分页,当然此种方式作为了解即可。我们来看下如何实现的!
步骤:
1、mapper接口

//选择全部用户RowBounds实现分页
List<User> getUserByRowBounds();

2、mapper文件

<select id="getUserByRowBounds" resultMap="user">
select * from user
</select>

3、测试类
在这里,我们需要使用RowBounds类

    @Test
    public void testUserByRowBounds() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        int currentPage = 2;  //第几页
        int pageSize = 2;  //每页显示几个
        RowBounds rowBounds = new RowBounds((currentPage-1)*pageSize,pageSize);
        //通过session.**方法进行传递rowBounds,[此种方式现在已经不推荐使用了]
        List<User> users = sqlSession.selectList("com.l.dao.UserMapper.getUserByRowBounds", null, rowBounds);
        for (User user: users){
            System.out.println(user);
        }
        sqlSession.close();
    }

在这里插入图片描述

15.使用注解开发

返回目录
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意利用注解开发就不需要mapper.xml映射文件了删除!
1、注解在接口上实现

    @Select("select * from user;")
    List<User> getUsers();

2、需要在核心配置文件中绑定接口!

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

3、测试使用

    @Test
    public void getUserById(){
         SqlSession sqlSession = MybatisUtils.getSqlSession();
         //底层主要应用反射
         UserMapper mapper = sqlSession.getMapper(UserMapper.class);
         List<User> user=mapper.getUsers();
        for (User user1 : user) {
            System.out.println(user1);
        }
         sqlSession.close();
    }

结果:这里的密码为空,自己改一下User类密码属性名就行了
在这里插入图片描述
本质:反射机制实现
底层:动态代理
利用Debug查看本质:
在这里插入图片描述
本质上利用了jvm的动态代理机制
在这里插入图片描述

16.Mybatis执行流程剖析

返回目录

Mybatis详细的执行流程
在这里插入图片描述

17.注解增删改查

返回目录
我们可以在工具类创建的时候实现自动提交事务!,不用再写commit方法了

//工具类中创建sqlSession改为下面代码
SqlSession sqlSession = sqlSessionFactory.openSession(true);

注解实现CRUD:

	//查询所有的用户
    @Select("select * from user;")
    List<User> getUsers();
    /*方法存在多个参数,所有的参数面前必须添加@Param("")*/
    @Select("select * from user where id=#{id} and name=#{name}")
    User getUserById(@Param("id")int id,@Param("name")String name);
    //增加一个用户
    @Insert("insert into user(id,name,pwd) values(#{id},#{name},#{pwd})")
    int addUser(User user);
    //更新一条用户数据
    @Update("update user set name=#{name},pwd=#{pwd} where id = #{id}")
    int updateUser(User user);
    //根据id删除用用户
    @Delete("delete from user where id = #{id}")
    int deleteUser(@Param("id")int id

测试方法:

package com.l.dao;

import com.l.pojo.User;
import com.l.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;


public class UserDaoTest {

    @Test
    public void getUsers(){
         SqlSession sqlSession = MybatisUtils.getSqlSession();
         //底层主要应用反射
         UserMapper mapper = sqlSession.getMapper(UserMapper.class);
         List<User> user=mapper.getUsers();
        for (User user1 : user) {
            System.out.println(user1);
        }
         sqlSession.close();
    }
    @Test
    public void getUserById(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user=mapper.getUserById(2,"李四");
        System.out.println(user);
        sqlSession.close();
    }
    @Test
    public void addUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(mapper.addUser(new User(5,"李奶奶","1112")));

        sqlSession.close();
    }
    @Test
    public void updateUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(mapper.updateUser(new User(5,"李奶奶个腿","11112222")));
        sqlSession.close();
    }
    @Test
    public void deleteUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(mapper.deleteUser(5));
        sqlSession.close();
    }
}

再提一下@Param注解,

  • 基本数据类型的参数或者String类型,需要加上
  • 引用数据类型不需要加
  • 如果只有一个基本类型的话,可以忽略,但是建议大家加上
  • 我们在SQL中引用的就是我们这里的@Param()中设定的属性名

18.Lombok的使用

返回目录
简介:

  • java library
  • plugs
  • build tools
  • with one annotation your class

使用步骤:

  1. 在IDEA中安装Lombok(设置-搜索插件-下载)

  2. 在项目中导入lombok的jar包

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

@Data注解帮我们自动封装无参构造,getter、setter方法,equals方法,hashCode方法,toString方法还有个canEqual方法
@ToString:生成toString方法
@EqualsAndHashCode生成equals和hashCode方法
@AllArgsConstructor生成有参构造方法
@NoArgsConstructor生成无参构造方法

@Getter生成getter方法,可以放在类或相应属性上

19.复杂查询环境搭建

返回目录
多个学生,对应一个老师
对于学生这边而言,关联… 多个学生,关联一个老师【多对一】
对于老师而言,集合,一个老师,有很多学生
在这里插入图片描述
学生通过tid关联老师的id

CREATE TABLE `teacher` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老师');

CREATE TABLE `student` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`tid` INT(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fktid` (`tid`),
CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8


INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小红', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小张', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');

测试环境搭建

  1. 导入lombok
		<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
        </dependency>
  1. 新建实体类 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;
}
  1. 建立Mapper接口
public interface StudentMapper {

}
public interface TeacherMapper {
    @Select("select * from teacher where id=#{tid}")
    Teacher getTeacher(@Param("tid")int id);
}
  1. 建立Mapper.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.l.dao.TeacherMapper">

</mapper>
<?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.l.dao.StudentMapper">

</mapper>
  1. 在核心配置文件中绑定注册我们的Mapper接口或者文件!【方式很多,随心选】
    在这里插入图片描述

  2. 测试查询是否成功

查询类:

public static void main(String[] args) {
        SqlSession sqlSession= MybatisUtils.getSqlSession();
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        Teacher teacher=mapper.getTeacher(1);
        System.out.println(teacher);
        sqlSession.close();
    }

结构图:
在这里插入图片描述
在resources下映射相同路径就不用再写资源过滤了

运行结果
在这里插入图片描述

20.多对一的处理

返回目录
引言:
在sql语句中想要多对一查询的语句:

select student.id,student.name,teacher.name from student,teacher where student.id=teacher.id

结果:
在这里插入图片描述
在mybatis中就没有那么简单了
方式一、按照查询嵌套处理(了解):
在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.l.dao.StudentMapper">
    <!--
        思路:
        1.查询所有的学生信息
        2.根据查询出来的学生的tid,寻找对应的老师
        相当于子查询
    -->
    <select id="getStudent" resultMap="StudentTeacher">
        select * from student
    </select>

    <resultMap id="StudentTeacher" type="com.l.pojo.Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <!--复杂的属性,我们需要单独处理 对象:association 集合:collection-->
        <association property="teacher" column="tid" javaType="com.l.pojo.Teacher" select="getTeacher"/>
    </resultMap>
    <select id="getTeacher" resultType="com.l.pojo.Teacher">
        select * from teacher where id=#{id}
    </select>

</mapper>

测试:

 @org.junit.Test
    public void test01(){
        SqlSession sqlSession= MybatisUtils.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> student = mapper.getStudent();
        for (Student student1 : student) {
            System.out.println(student1);
        }
        sqlSession.close();
    }

运行结果:
在这里插入图片描述
方式二、按照结果嵌套处理(掌握):
StudentMapper接口新加方法:

public List<Student> getStudent02();

StudentMapper.xml配置:

 <select id="getStudent02" resultMap="StudentTeacher02">
        select student.id,student.name,teacher.name
        from student,teacher
        where student.tid=teacher.id
    </select>
    <resultMap id="StudentTeacher02" type="com.l.pojo.Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <association property="teacher" javaType="com.l.pojo.Teacher">
            <result property="name" column="name"/>
         </association>
    </resultMap>

测试:

 @org.junit.Test
    public void test02(){
        SqlSession sqlSession= MybatisUtils.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> student = mapper.getStudent02();
        for (Student student1 : student) {
            System.out.println(student1);
        }
        sqlSession.close();
    }

结果:
在这里插入图片描述

21.一对多的处理

返回目录
比如一个老师有多个学生
第一步还是环境搭建:
实体类:Student和Teacher

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

对应的接口

public interface StudentMapper {

}
public interface TeacherMapper {
    //获取老师
    List<Teacher> getTeacher();
}

TeacherMapper.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.l.dao.TeacherMapper">
    <select id="getTeacher" resultType="com.l.pojo.Teacher">
        select * from mybatis.teacher
    </select>
</mapper>

主配置:
db.properties文件:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&useSSL=false&character=UTF-8&serverTimezone=GMT%2B8
username=root
password=198810
<?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"><!--第一步引入外部配置文件-->
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </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>
        <package name="com.l.dao"/>
    </mappers>

</configuration>

测试:

 @org.junit.Test
    public void test01(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        List<Teacher> teacher = mapper.getTeacher();
        for (Teacher teacher1 : teacher) {
            System.out.println(teacher1);
        }
    }

结果:
在这里插入图片描述
环境搭建成功!!!
引言:
在sql语句中想要多对一查询的语句:

select student.id sid,student.name sname,teacher.name tname,teacher.id tid from teacher,student where tid=teacher.id;

结果:
在这里插入图片描述
方式一、按照查询嵌套处理(了解)

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

    <select id="getStudentByTeacherId" resultType="com.l.pojo.Student">
        select * from mybatis.student where tid=${tid}
    </select>

方式二、按照结果嵌套处理(掌握)
TeacherMapper.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.l.dao.TeacherMapper">
    <select id="getTeacher" resultMap="TeacherStudent">
        select student.id sid,student.name sname,teacher.name tname,teacher.id tid
        from teacher,student where student.tid=teacher.id and teacher.id=#{tid};
    </select>
    <resultMap id="TeacherStudent" type="com.l.pojo.Teacher">
        <!--
        在结果嵌套查询中
        对象用:association
        集合用:collection
        javaType:指定属性类型
        ofType:集合中的泛型信息


        显而易见:在多对一中association常搭配javaType
                在一对多中collection常搭配ofType
        -->
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
       <collection property="students" ofType="com.l.pojo.Student">
           <result property="id" column="sid"/>
           <result property="name" column="sname"/>
           <result property="tid" column="tid"/>
       </collection>
    </resultMap>
</mapper>

其余不变的情况下,修改测试方法:

@org.junit.Test
    public void test02(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        teacher = mapper.getTeacher(1);
        System.out.println(teacher.getName());
        sqlSession.close();
    }

结果:
在这里插入图片描述
在这里插入图片描述

22.动态SQL环境搭建

返回目录

23.动态SQL之IF语句

返回目录

24.动态SQL之常用标签

返回目录

25.动态SQL之Foreach

返回目录

26.缓存简介

返回目录

27.一级缓存

返回目录

28.二级缓存

返回目录

29.Mybatis缓存原理

返回目录

30.自定义缓存Ehcache

返回目录

31.Mybatis总结

返回目录

32.聊聊Spring这东西

返回目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CharmDeer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值