• 【Java框架 一】Mybatis


    一、Mybatis

    官方文档:https://mybatis.org/mybatis-3/zh/index.html

    1、Mybatis简介

    1.1 什么是Mybatis

    • MyBatis 是一款优秀的持久层框架

    • 它支持自定义 SQL、存储过程以及高级映射

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

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

    1.2 获取Mybatis

    
    <dependency>
        <groupId>org.mybatisgroupId>
        <artifactId>mybatisartifactId>
        <version>3.5.11version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2、第一个Mybatis

    2.1 搭建环境

    2.1.1 搭建数据库
    CREATE DATABASE mybatis;
    USE mybatis;
    CREATE TABLE `user` (
    	`id` INT(20) NOT NULL,
    	`name` VARCHAR(30) DEFAULT NULL,
    	`pwd` VARCHAR(30) DEFAULT NULL,
    	PRIMARY KEY(`id`)
    ) ENGINE=INNODB DEFAULT CHARSET=utf8;
    INSERT INTO `user`(`id`,`name`,`pwd`) VALUES
    (1,'张三','123123'),
    (2,'李四','111111'),
    (3,'王五','121212');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    2.1.2 新建项目
    1. 创建一个普通的maven项目

    2. 删除src目录使其变成一个父工程

    3. 导入依赖

      1. <dependency>
                    <groupId>mysqlgroupId>
                    <artifactId>mysql-connector-javaartifactId>
                    <version>5.1.49version>
                dependency>
                <dependency>
                    <groupId>org.mybatisgroupId>
                    <artifactId>mybatisartifactId>
                    <version>3.5.11version>
                dependency>
                <dependency>
                    <groupId>junitgroupId>
                    <artifactId>junitartifactId>
                    <version>4.12version>
                dependency>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15

    2.2 创建一个模块

    之后我们的项目都是一个个模块

    2.2.1 编写核心配置文件
    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "https://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.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf-8"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                dataSource>
            environment>
        environments>
        <mappers>
            <mapper resource="com/daban/dao/UserMapper.xml"/>
        mappers>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    2.2.2 编写工具类
    package com.daban.utils;
    
    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;
    
    public class MybatisUtils {
        private static SqlSessionFactory sqlSessionFactory;
        static {
            try {
                String resource = "mybatis-config.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
        public static SqlSession getSqlSession(){
            return sqlSessionFactory.openSession();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    2.3 编写代码

    2.3.1 可能会遇到的错误
    • org.apache.ibatis.binding.BindingException: Type interface com.daban.dao.UserDao is not known to the MapperRegistry.

      意思是没有在mybatis的配置文件中注册mapper,需要在配置文件中添加注册

      <mappers>
          <mapper resource="com/daban/dao/UserMapper.xml"/>
      mappers>
      
      • 1
      • 2
      • 3
    • org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource com/daban/dao/UserMapper.xml

      不能找到mapper.xml文件,因为在构建的时候没有导出该文件,如下代码到pom中可以解决

    
        
            
                src/main/java
                
                    **/*.xml
                
                true
            
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • org.xml.sax.SAXParseException; lineNumber: 5; columnNumber: 14; 1 字节的 UTF-8 序列的字节 1 无效。

    是因为xml文件中的注释使用了中文,去掉即可,或者将encoding="UTF-8"改为encoding=“UTF8”(原因不明)

    2.3.2 实体类
    package com.daban.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;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", pwd='" + pwd + '\'' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    2.3.3 Dao接口
    package com.daban.dao;
    
    import com.daban.pojo.User;
    
    import java.util.List;
    
    public interface UserDao {
        List<User> getUserList();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    2.3.4 接口实现类

    (由之前的实现类转变成一个Mapper配置文件)

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.daban.dao.UserDao">
    
    
        <select id="getUserList" resultType="com.daban.pojo.User">
            select * from mybatis
        select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    2.3.5 单元测试
    package com.daban.dao;
    
    import com.daban.pojo.User;
    import com.daban.utils.MybatisUtils;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.List;
    
    public class UserMapperTest {
        @Test
        public void test(){
            //获取sqlSession
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            //得到UserDao的Mapper
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List<User> userList = mapper.getUserList();
            for (User user: userList) {
                System.out.println(user);
            }
            sqlSession.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    3、类作用域

    作用域备注
    SqlSessionFactoryBuilder最佳作用域是方法作用域(也就是局部方法变量)
    SqlSessionFactory最佳作用域是应用作用域想象为数据库连接池
    SqlSession最佳的作用域是请求或方法作用域连接到连接池的一个请求,用完关闭

    4、CURD

    记住,在增删改的时候需要提交事务才可以生效sqlSession.commit();

    4.1 select

    1、编写接口

    //通过id查询用户
    User getUserById(int id);
    
    • 1
    • 2

    2、编写对应mapper中的sql语句

    <select id="getUserById" resultType="com.daban.pojo.User" parameterType="int" >
        select * from mybatis.user where id = #{id}
    select>
    
    • 1
    • 2
    • 3

    3、测试

    public void getUserById(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User userById = mapper.getUserById(1);
        System.out.println(userById);
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4.2 insert

    1、编写接口

    //增加一个用户
    void addUser(User user);
    
    • 1
    • 2

    2、编写对应mapper中的sql语句

    <insert id="addUser" parameterType="com.daban.pojo.User">
            insert into mybatis.user values(#{id},#{name},#{pwd})
    insert>
    
    • 1
    • 2
    • 3

    3、测试

    public void addUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.addUser(new User(5,"嫦娥","333333"));
        //增删改必须要提交事务
        sqlSession.commit();
        sqlSession.close();
    }        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4.3 update

    1、编写接口

    //修改一个用户
    void updateUser(User user);
    
    • 1
    • 2

    2、编写对应mapper中的sql语句

    <update id="updateUser" parameterType="com.daban.pojo.User">
            update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id}
    update>
    
    • 1
    • 2
    • 3

    3、测试

    public void updateUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.updateUser(new User(5,"大圣","888888"));
        sqlSession.commit();
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4.4 delete

    1、编写接口

    //删除一个用户
    void deleteUser(User user);
    
    • 1
    • 2

    2、编写对应mapper中的sql语句

    <delete id="deleteUser" parameterType="com.daban.pojo.User">
            delete from mybatis.user where id=#{id}
    delete>
    
    • 1
    • 2
    • 3

    3、测试

    public void deleteUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.deleteUser(new User(5));
        sqlSession.commit();
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4.4 模糊查询

    1、编写接口

    //通过name查询用户
    List<User> getUserByName(String name);
    
    • 1
    • 2

    2、编写对应mapper中的sql语句

    <select id="getUserByName" resultType="com.daban.pojo.User" parameterType="string" >
        select * from mybatis.user where name like #{name}
    select>
    
    • 1
    • 2
    • 3

    3、测试

    public void getUserByName(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserByName("%张%");
        for (User user: userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    5、核心配置文件解析

    首先配置文件中标签是有顺序的,写反会报错

    properties>settings>typeAliases>typeHandlers>objectFactory>objectWrapperFactory>reflectorFactory>plugins>environments>databaseIdProvider>mappers

    5.1 属性(properties)

    引入一个配置文件,使mybatis的核心配置文件可以引用该配置文件里面的参数

    <properties resource="config.properties">
        
    	<property name="username" value="root"/>
        <property name="password" value="123456"/>
    properties>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    获取值的方式

    <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    如果一个属性在不只一个地方进行了配置,那么,MyBatis 将按照下面的顺序来加载:

    • 首先读取在 properties 元素体内指定的属性。
    • 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
    • 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。

    因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。

    5.2 设置(settings)

    这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为

    官网查找https://mybatis.org/mybatis-3/zh/configuration.html

    5.3 类型别名(typeAliases)

    类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写

    <typeAliases>
      <typeAlias alias="user" type="com.daban.pojo.User"/>
    typeAliases>
    
    • 1
    • 2
    • 3

    可以通过包来起别名,包下的所有实体类,都可以使用类名的首字母小写来代替全名,给实体类加注解,可以diy

    <typeAliases>
      <package name="com.daban.pojo"/>
    typeAliases>
    
    • 1
    • 2
    • 3

    5.4 环境配置(environments)

    <environments default="development">默认使用的环境
        <environment id="development">定义的环境标识,可随意标识,保证默认的环境 ID 要匹配其中一个环境 ID
            <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    5.4.1 事务管理器

    在 MyBatis 中有两种类型的事务管理器(也就是 type=“[JDBC|MANAGED]”)

    如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置

    5.4.2 数据源

    有三种内建的数据源类型(也就是 type=“[UNPOOLED|POOLED|JNDI]”),

    UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择

    POOLED(常用)– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间

    JNDI – 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用

    5.5 映射器(mappers)

    告诉 MyBatis 到哪里去找到sql语句

    方式一、【推荐使用】

    
    <mappers>
        <mapper resource="com/daban/dao/UserMapper.xml"/>
    mappers>
    
    • 1
    • 2
    • 3
    • 4

    方式二、

    
    <mappers>
        <mapper class="com.daban.dao.UserMapper"/>
    mappers>
    
    • 1
    • 2
    • 3
    • 4

    注意点:

    • 接口和他的mapper配置文件必须同名

    • 接口和他的mapper配置文件必须在同一个包下

    方式三、

    
    <mappers>
        <package name="com.daban.dao"/>
    mappers>
    
    • 1
    • 2
    • 3
    • 4

    注意点:

    • 接口和他的mapper配置文件必须同名

    • 接口和他的mapper配置文件必须在同一个包下

    方式四、【不建议使用】

    
    <mappers>
      <mapper url="file:///var/mappers/AuthorMapper.xml"/>
    mappers>
    
    • 1
    • 2
    • 3
    • 4

    6、mapper配置文件解析

    6.1 select标签

    <select id="getUserById" resultType="com.daban.pojo.User" parameterType="int" >
        select * from mybatis.user where id = #{id}
    select>
    
    • 1
    • 2
    • 3

    select元素的属性

    <select
      id="selectPerson"                      dao接口中的方法名字
      parameterType="int"                    参数的类全限定名或别名。这个属性是可选的
      parameterMap="deprecated"              废弃了
      resultType="hashmap"                   返回结果的类全限定名或别名,如果是集合,写集合泛型
      resultMap="personResultMap"            对实体类和字段名字不一样时的处理,结果映射
      flushCache="false"                     每次sql执行,都刷新清除一二级缓存
      useCache="true"                        开启二级缓存
      timeout="10"                           在抛出异常之前,驱动程序等待数据库返回请求结果的秒数
      fetchSize="256"                        尝试让驱动程序每次批量返回的结果行数等于这个设置值
      statementType="PREPARED"				 可选 STATEMENT,PREPARED  CALLABLE
      resultSetType="FORWARD_ONLY">		
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    6.2 insert, update 和 delete

    <insert id="insertAuthor">
      insert into Author (id,username,password,email,bio)
      values (#{id},#{username},#{password},#{email},#{bio})
    insert>
    
    <update id="updateAuthor">
      update Author set
        username = #{username},
        password = #{password},
        email = #{email},
        bio = #{bio}
      where id = #{id}
    update>
    
    <delete id="deleteAuthor">
      delete from Author where id = #{id}
    delete>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    属性

    <insert
      keyProperty=""                     设置自增主键的字段
      keyColumn=""
      useGeneratedKeys=""                开启自增主键
      timeout="20">
    
    • 1
    • 2
    • 3
    • 4
    • 5

    6.3 结果映射resultMap

    ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了

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

    方式一、起别名

    <select id="getUserById" resultType="com.daban.pojo.User" parameterType="int" >
        select user_id as id,
               user_name,
               user_pwd 
               from mybatis.user where id = #{id}
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    方式二、使用resultMap

    <resultMap id="userResultMap" type="User">
      <id property="id" column="user_id" />
      <result property="username" column="user_name"/>
      <result property="password" column="user_password"/>
    resultMap>
    <select id="getUserById" resultMap="userResultMap" parameterType="int" >
        select from mybatis.user where id = #{id}
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    6.3.2 resultMap标签的属性
    标签解释备注
    id当前命名空间中的一个唯一标识,用于标识一个结果映射。和select标签中的 resultMap绑定
    type类的完全限定名, 或者一个类型别名。不用结果集映射时,select标签中的resultType的值
    autoMapping如果设置这个属性,MyBatis 将会为本结果映射开启或者关闭自动映射
    6.3.3 resultMap标签的子标签
    标签解释备注
    constructor用于在实例化类时,注入结果到构造方法中
    id标记出作为 ID 的结果可以帮助提高整体性能
    result注入到字段或 JavaBean 属性的普通结果
    association个复杂类型的关联;许多结果将包装成这种类型相当于对象
    collection一个复杂类型的集合相对于集合
    discriminator使用结果值来决定使用哪个

    6.4 sql片段

    这个元素可以用来定义可重用的 SQL 代码片段,以便在其它语句中使用

    <sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password sql>
    
    • 1
    <include refid="userColumns"><property name="alias" value="t1"/>include>
    
    • 1

    7、日志

    7.1 日志工厂

    <settings>
        
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    settings>
    
    • 1
    • 2
    • 3
    • 4

    设置里设置logImpl的值:

    SLF4J

    LOG4J(3.5.9 起废弃)

    LOG4J2

    JDK_LOGGING

    COMMONS_LOGGING

    STDOUT_LOGGING

    NO_LOGGING

    7.2 LOG4J

    1、先导包

    <dependency>
        <groupId>log4jgroupId>
        <artifactId>log4jartifactId>
        <version>1.2.17version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2、配置log4j的配置文件

    resources下新建一个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/logFile.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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    3、使用

    import org.apache.log4j.Logger;
    Logger logger = Logger.getLogger(UserTest.class);//获得logger对象,参数为当前类的class
    
    • 1
    • 2
    logger.info("我是info");
    logger.debug("我是调试信息");
    logger.error("我是error");
    
    • 1
    • 2
    • 3

    8、分页的实现

    原理就是使用map来传递limit的参数

    1、接口方法

    List<User> getUserListLimit(Map<String,Object> map);
    
    • 1

    2、mapper配置文件

    <mapper namespace="com.daban.dao.UserMapper">
        <resultMap id="userMap" type="user">
            <result property="password" column="pwd"/>
        resultMap>
    
        <select id="getUserListLimit" resultMap="userMap" parameterType="map">
            select * from mybatis.user limit #{startIndex},#{pageSize}
        select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3、测试

    public void test(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Map<String, Object> map = new HashMap<>();
        map.put("startIndex",2);
        map.put("pageSize",3);
        List<User> userList = mapper.getUserListLimit(map);
        for (User user : userList) {
            System.out.println(user);
        }
    
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    9、使用注解开发

    9.1 基本使用

    使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句

    1、删除接口的mapper文件

    2、接口中使用注解

    @Select("select * from mybatis.user")
    List<User> getUserList();
    
    • 1
    • 2

    3、mybatis核心配置文件中使用类绑定

    <mappers>
         <mapper class="com.daban.dao.UserMapper"/>
    mappers>
    
    • 1
    • 2
    • 3

    这样会发现无法进行结果集映射,这是使用注解的弊端

    9.2 CRUD

    SqlSession sqlSession = factory.openSession(true);//参数为是否自动提交,设置true后,不需要手动提交
    //但是在使用注解时,会自动提交
    
    • 1
    • 2
    public interface UserMapper {
        //查询所有
        @Select("select * from mybatis.user")
        List<User> getUserList();
        
        //查询,一个参数可以省略@Param
        @Select("select * from mybatis.user where id = #{id}")
        User getUserById(int id);
        
        //查询俩个参数,不能省略@Param
        @Select("select * from mybatis.user where id = #{id} and name = #{name}")
        User getUserByIdAndName(@Param("id") int id,@Param("name") String name);
        
        //增加
        @Select("insert into mybatis.user values(#{id},#{name},#{password})")
        void addUser(User user);
        
        //修改
        @Select("update mybatis.user set name=#{name},pwd=#{password} where id = #{id} ")
        void updateUser(User user);
        
        //删除
        @Select("delete from mybatis.user where id = #{id}")
        void deleteUser(User user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    9.3 关于@Param(“id”)

    • 基本参数类型和String类型需要加上
    • 引用类型不需要加
    • 如果只有一个基本类型,可以忽略,建议加上

    10、lombok(偷懒专用)

    1、idea中的plugin中安装lombok

    2、导入lombok的jar包

    
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <version>1.18.24version>
        <scope>providedscope>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3、使用

    在实体类上加注解就行

    @Getter//get方法
    @Setter//set方法
    @ToString//ToString方法
    @EqualsAndHashCode//EqualsAndHashCode方法
    @NoArgsConstructor//无参构造方法
    @Data//以上都创建了
    
    @AllArgsConstructor//所有参数构造方法
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    11、多对一association

    其实就是解决属性名和字段名不一致的问题,因为联表查询把其他表的字段放在了该表里,名称类型可能不一致

    准备sql

    CREATE TABLE teacher(
    	`id`  INT(20) 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(20) NOT NULL,
    	NAME VARCHAR(30) DEFAULT NULL,
    	`tid` INT(10) DEFAULT NULL,
    	PRIMARY KEY (`id`),
    	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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    实体类

    @Data
    public class Student {
        private int id;
        private String name;
    
        private Teacher teacher;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    @Data
    public class Teacher {
        private int id;
        private String name;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    mapper文件

    <mapper namespace="com.daban.dao.StudentMapper">
    
    
        <resultMap id="getStudentListMap1" type="com.daban.pojo.Student">
            <result property="id" column="s_id"/>
            <result property="name" column="s_name"/>
            <association property="teacher" javaType="com.daban.pojo.Teacher" >
                <result property="name" column="t_name"/>
                <result property="id" column="t_id"/>
            association>
        resultMap>
        <select id="getStudentList1" resultMap="getStudentListMap1">
            select s.id as s_id,
                   s.name as s_name,
                   t.name as t_name,
                   t.id as t_id
            from mybatis.student s , mybatis.teacher t
            where t.id  = s.tid
        select>
    
    
        <resultMap id="getStudentListMap2" type="com.daban.pojo.Student">
            <result property="id" column="id"/>
            <result property="name" column="name"/>
            <association property="teacher" column="tid" javaType="com.daban.pojo.Teacher"
                         select="getTeacherList"/>
        resultMap>
        <select id="getStudentList2" resultMap="getStudentListMap2">
            select * from mybatis.student
        select>
        <select id="getTeacherList" resultType="com.daban.pojo.Teacher">
            select * from mybatis.teacher where id = #{id}
        select>
    
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    12、一对多collection

    其实就是解决属性名和字段名不一致的问题,因为联表查询把其他表的字段放在了该表里,名称类型可能不一致

    实体类

    @Data
    public class Teacher {
        private int id;
        private String name;
        private List<Student> student;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    @Data
    public class Student {
        private int id;
        private String name;
        private int tid;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    mapper文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.daban.dao.TeacherMapper">
        
        <resultMap id="getTeacherListMap1" type="com.daban.pojo.Teacher">
            <result property="id" column="t_id"/>
            <result property="name" column="t_name"/>
            <collection property="student" column="t_id" ofType="com.daban.pojo.Student">
                <result property="id" column="s_id"/>
                <result property="name" column="s_name"/>
                <result property="tid" column="s_tid"/>
            collection>
        resultMap>
        <select id="getTeacherList1" resultMap="getTeacherListMap1">
            select t.id as t_id,
                   t.name as t_name,
                   s.id as s_id,
                   s.name as s_name,
                   s.tid as s_tid
            from mybatis.teacher t,mybatis.student s where s.tid=t.id;
        select>
    
        
        <resultMap id="getTeacherListMap2" type="com.daban.pojo.Teacher">
            <result property="id" column="id"/>
            <result property="name" column="name"/>
            <collection property="student" column="id" ofType="com.daban.pojo.Student"
                        javaType="ArrayList" select="getStudentList"/>
        resultMap>
        <select id="getTeacherList2" resultMap="getTeacherListMap2">
            select * from mybatis.teacher
        select>
        <select id="getStudentList" resultType="com.daban.pojo.Student">
            select * from mybatis.student where tid = #{tid}
        select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    13、 动态sql

    13.1 准备数据

    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        开启数据库下划线命名和实体类属性驼峰命名的对应
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    settings>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    根据不同的条件生成不同的sql语句

    sql准备

    CREATE TABLE blog(
    	`id`  INT(50) NOT NULL,
    	`title` VARCHAR(100) NOT NULL,
    	`author` VARCHAR(30) NOT NULL,
    	`create_time` DATETIME NOT NULL,
    	`views` INT(30) NOT NULL
    
    )ENGINE INNODB DEFAULT CHARSET=utf8;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    表中插入数据:

    <insert id="addBlog" parameterType="blog">
        insert into mybatis.blog(`id`,`title`,`author`,`create_time`,`views`)
        values (#{id},#{title},#{author},#{createTime},#{views});
    insert>
    
    • 1
    • 2
    • 3
    • 4
    public void addBlog(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        mapper.addBlog(new Blog(IDUtils.getID(),"庆祝二十大顺利召开","中央视频",new Date(),9999));
        mapper.addBlog(new Blog(IDUtils.getID(),"中纪委公布查处中央委员人数","中央视频",new Date(),500));
        mapper.addBlog(new Blog(IDUtils.getID(),"小学生捡到“十万元”组团交派出所","华商报",new Date(),2344));
        mapper.addBlog(new Blog(IDUtils.getID(),"浪漫同框!中国空间站飞越北京上空","华商报",new Date(),555));
        mapper.addBlog(new Blog(IDUtils.getID(),"中国要搞自给自足?发改委:误解","四川观察",new Date(),1234));
        sqlSession.commit();
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    13.2 if使用

    注意map中的key要和if里面的title对应上(名称一致)

    当sql语句中包含小于号时,不被识别。只能使用大于号,解决办法,前后颠倒要比较的值

    <select id="queryBlogIf" resultType="blog" parameterType="map">
        select * from mybatis.blog where 1=1
        <if test="title!=null">
            and title like #{title}
        if>
        <if test="views!=null">
            and #{views} > views
        if>
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    public void queryBlogIf(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        Map<String, Object> map = new HashMap<>();
        map.put("title","%中%");
        map.put("views",1000);
        List<Blog> blogs = mapper.queryBlogIf(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    13.3 choose、when、otherwise

    类似与java的switch case语句:第一个满足条件后面都不执行了,都不满足执行otherwise

    <select id="queryBlogChoose" resultType="blog" parameterType="map">
        select * from mybatis.blog where 1=1
        <choose>
            <when test="title!=null">
                and title like #{title}
            when>
            <when test="author!=null">
                and #{author} = author
            when>
            <otherwise>
                and #{views} > views
            otherwise>
        choose>
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    public void queryBlogChoose(){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
            Map<String, Object> map = new HashMap<>();
    //        map.put("title","%中%");
            map.put("author","华商报");
            map.put("views",1000);
            List<Blog> blogs = mapper.queryBlogChoose(map);
            for (Blog blog : blogs) {
                System.out.println(blog);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    13.4 trim、where、set

    where 元素自动插入 “WHERE” 。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除

    set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)

    where和set都可以使用trim实现,只不过,trim更可以自定义

    13.5 Foreach

    <select id="queryBlogForeach" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <foreach collection="viewsList" item="view" open="(" separator="or" close=")">
                views = #{view}
            foreach>
        where>
    
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    public void queryBlogForeach(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        Map<String, Object> map = new HashMap<>();
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(9999);
        arrayList.add(2344);
        map.put("viewsList",arrayList);
        List<Blog> blogs = mapper.queryBlogForeach(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    14、缓存

    查询的结果放在内存中,我们再次查询相同数据时,就可以走缓存,从而减少数据库的连接,减低资源损耗

    经常查询且不经常改变的数据,可以使用缓存

    创建实体类时,要实现序列化,这样对象才能被缓存,不然报错

    mybatis默认两级缓存:

    • 一级缓存:默认开启,sqlsession级别的缓存
    • 二级缓存:需要手动开启,namespace级别的缓存

    14.1 一级缓存

    缓存失效的情况:

    ​ 1、查询不同的数据

    ​ 2、增删改操作,可能会改变原来的数据,所以必定会刷新缓存

    ​ 3、查询不同的mapper.xml

    ​ 4、手动清理缓存(sqlSession.clearCache();)

    14.2 二级缓存

    打开方式:在mapper文件中加入标签即可开启二级缓存

    会话关闭时,就会将一级缓存中的数据保存到二级缓存,新的会话查询就会从二级缓存查询

    14.3 自定义缓存ehcache

    java的分布式缓存

    1、先导包

    
    <dependency>
        <groupId>org.mybatis.cachesgroupId>
        <artifactId>mybatis-ehcacheartifactId>
        <version>1.2.2version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2、mapper文件中设置

    <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
    
    • 1

    3、增加配置文件ehcache.xml

    
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
        
        <diskStore path="java.io.tmpdir/ehcache"/>
    
             
        
        <defaultCache
                       
               maxElementsInMemory="10"
               eternal="false"
               timeToIdleSeconds="3600"
               timeToLiveSeconds="3600"
               overflowToDisk="true"
               memoryStoreEvictionPolicy="LRU"/>
    
        
        <cache name="deptrole"
               maxElementsInMemory="10"
               eternal="false"
               timeToIdleSeconds="86400"
               timeToLiveSeconds="86400"
               overflowToDisk="true"
               memoryStoreEvictionPolicy="LRU"/>
    
    ehcache>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    15、作业

    用mybatis重新写smbms项目

  • 相关阅读:
    SPASS-图表的创建&编辑
    【第 8 章 MySQL InnoDB ClusterSet 】
    【汇编】初识,汇编是什么呢?
    windows修改默认端口3389
    日期时间参数,格式配置(SpringBoot)
    unity操作_Camera c#
    【ODPS 新品发布第 2 期】实时数仓 Hologres:推出计算组实例/支持 JSON 数据/向量计算+大模型等新能力
    java数组之冒泡排序、快速排序
    最接地气的.NET微服务框架
    C语言之:数组的定义和初始化必备练习题
  • 原文地址:https://blog.csdn.net/daban2008/article/details/127720663