MyBatis


MyBatis

环境:

  • JDK1.8

  • Mysql 5.7

  • Maven 3.6.3

  • IDEA

1. 简介

1.1 什么是MyBatis

  • MyBatis是一款优秀的持久层框架(数据访问层又称为DAL层,有时候也称为是持久层,其功能主要是负责数据库的访问)
  • 它支持自定义 SQL、存储过程以及高级映射。
  • MyBatis 免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。
  • MyBatis可以通过简单的 XML或注解来配置和映射原始类型、接口和Java POJOPlain Old Java Objects,普通老式Java对象)为数据库中的记录。
  • MyBatis本是apache的一个开源项目iBatis
  • 2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis
  • 2013年11月迁移到Github

1.2 MyBatis相关网址链接

  • GitHub:https://github.com/mybatis/mybatis-3

  • MyBatis官网中文文档:https://mybatis.org/mybatis-3/zh/index.html

  • MyBatis官网:https://mybatis.org

  • Maven仓库:https://mvnrepository.com/search?q=Mybatis

1.3 数据持久化

  • 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
  • 内存:断电即失
  • 数据库、IO文件

1.4 为什么需要使用MyBatis

  • 方便
  • 简化JDBC代码
  • 帮助程序员将数据存入到数据库中
  • 框架自动化

2. 第一个MyBatis程序

2.1 搭建MySQL/Oracle数据库

CREATE DATABASE `MyBatis`;
USE `MyBatis`;
CREATE TABLE `Account` 
(
	`id` INT(8) NOT NULL AUTO_INCREMENT, 
	`accId` VARCHAR(20) NOT NULL, 
	`passWord` VARCHAR(50) NOT NULL, 
	`notes` VARCHAR(200) DEFAULT NULL, 
	PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=UTF8;
SELECT id, accId, passWord, notes 
FROM Account;

2.2 搭建Maven项目环境

2.2.1 导入POM依赖


    
    
        junit
        junit
        4.12
    
    
    
        com.github.noraui
        ojdbc8
        12.2.0.1
    
    
    
        app.myoss.cloud.mybatis
        myoss-mybatis
        2.1.7.RELEASE
    
    
    
        org.projectlombok
        lombok
        1.18.20
        provided
    




    
        
            src/main/resources
            
                **/*.properties
                **/*.xml
            
            true
        
        
            src/main/java
            
                **/*.properties
                **/*.xml
            
            true
        
    

2.2.2 在resources文件夹下创建一个文件,命名为:mybatis-config.xml

<?xml version="1.0" encoding="UTF8" ?>



    
        
            
            
                
                
                
                
            
        
    
    
    
    
        
    

2.2.3 编写代码

  • 编写MyBatis工具类

    package com.xjbh.uitls;
    
    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 MyBatisUtil {
        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();
        }
    }
    
  • 编写实体类

    package com.xjbh.entity;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class EAS_Sale {
        private String sDate;
        private String shopId;
        private int manageDeptId;
        private double saleValue;
        private double saleTaxRate;
        private int flag;
        private int venderId;
    }
    
  • 编写EAS_SaleMapper接口

    package com.xjbh.mapper;
    
    import com.xjbh.entity.EAS_Sale;
    
    import java.util.List;
    
    public interface EAS_SaleMapper {
        List getSaleList();
    }
    
  • 编写实现类转变为EAS_SaleMapper.xml的配置文件

    <?xml version="1.0" encoding="UTF8" ?>
    
    
    
    
        
        
    
    

2.2.4 测试

import com.xjbh.entity.EAS_Sale;
import com.xjbh.uitls.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class EAS_SaleMapperTest {
    @Test
    public void getSalesTest() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        // 方法一:通过getMapper()方法
        EAS_SaleMapper mapper = sqlSession.getMapper(EAS_SaleMapper.class);
        List saleList = mapper.getSaleList();

        // 方法二:不推荐使用
        // List saleList = sqlSession.selectList("com.xjbh.mapper.EAS_SaleMapper.getSaleList");
        
        for (EAS_Sale eas_sale : saleList) {
            System.out.println(eas_sale);
        }
        sqlSession.close();
    }
}

3. CRUD语句

3.1 namespace

namespace中的包名必须与mapper接口保持一致

3.2 Create

  • id:对应namespace中的方法名

  • parameterType:参数类型,如果参数类型为实体类型,则可以在SQL的参数中访问实体类属性

    EAS_SaleMapper接口类

    package com.xjbh.mapper;
    
    import com.xjbh.entity.EAS_Sale;
    
    import java.util.List;
    
    public interface EAS_SaleMapper {
        int insertEAS_Sale(EAS_Sale easSale);
    }
    

    EAS_SaleMapper.xml接口配置文件

    <?xml version="1.0" encoding="UTF8" ?>
    
    
    
    
        
        
            INSERT INTO QXINTERFACE.SALE_CWJK(sdate, shopid, managedeptid, salevalue, saletaxrate, flag, venderid)
            VALUES(#{sDate}, #{shopId}, #{manageDeptId}, #{saleValue}, #{saleTaxRate}, #{flag}, #{venderId})
        
    
    

    测试代码

    package com.xjbh.mapper;
    
    import com.xjbh.entity.EAS_Sale;
    import com.xjbh.uitls.MyBatisUtil;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.List;
    
    public class EAS_SaleMapperTest {
        @Test
        public void insertEAS_SaleTest() {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            EAS_SaleMapper mapper = sqlSession.getMapper(EAS_SaleMapper.class);
            mapper.insertEAS_Sale(new EAS_Sale("2021-10-11", "D011", 16, 110.00, 13, 0, 110001));
    
            // CUD语句需要提交事务
            sqlSession.commit();
            sqlSession.close();
        }
    }
    

3.3 Retrieve

  • id:对应namespace中的方法名

  • resultTypeSQL语句执行的返回值

  • parameterType:参数类型,如果参数类型为实体类型,则可以在SQL的参数中访问实体类属性

    EAS_SaleMapper接口类

    package com.xjbh.mapper;
    
    import com.xjbh.entity.EAS_Sale;
    
    import java.util.List;
    
    public interface EAS_SaleMapper {
        List getSaleList();
        List getSaleListByShopId(String shopId);
        EAS_Sale getSaleListByEAS_Sale(EAS_Sale easSale);
    }
    

    EAS_SaleMapper.xml接口配置文件

    <?xml version="1.0" encoding="UTF8" ?>
    
    
    
    
        
        
    
        
        
    
        
        
    
    

    测试代码

    package com.xjbh.mapper;
    
    import com.xjbh.entity.EAS_Sale;
    import com.xjbh.uitls.MyBatisUtil;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.List;
    
    public class EAS_SaleMapperTest {
        @Test
        public void getSaleListTest() {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            // 方法一:通过getMapper()方法
            EAS_SaleMapper mapper = sqlSession.getMapper(EAS_SaleMapper.class);
            List saleList = mapper.getSaleList();
    
            // 方法二:不推荐使用
            // List saleList = sqlSession.selectList("com.xjbh.mapper.EAS_SaleMapper.getSaleList");
    
            for (EAS_Sale eas_sale : saleList) {
                System.out.println(eas_sale);
            }
            sqlSession.close();
        }
    
        @Test
        public void getSaleListByShopIdTest() {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            EAS_SaleMapper mapper = sqlSession.getMapper(EAS_SaleMapper.class);
            List saleList = mapper.getSaleListByShopId("D011");
    
            for (EAS_Sale eas_sale : saleList) {
                System.out.println(eas_sale);
            }
            sqlSession.close();
        }
    
        @Test
        public void getSaleListByEAS_SaleTest() {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            EAS_SaleMapper mapper = sqlSession.getMapper(EAS_SaleMapper.class);
            EAS_Sale easSale = mapper.getSaleListByEAS_Sale(new EAS_Sale("2021-10-11", "D011", 16, 110.00, 13, 0, 110001));
            System.out.println(easSale);
    
            sqlSession.close();
        }
    }
    

3.4 Update

  • id:对应namespace中的方法名

  • parameterType:参数类型,如果参数类型为实体类型,则可以在SQL的参数中访问实体类属性

    EAS_SaleMapper接口类

    package com.xjbh.mapper;
    
    import com.xjbh.entity.EAS_Sale;
    
    import java.util.List;
    
    public interface EAS_SaleMapper {
        int updateEAS_SaleByEAS_Sale(EAS_Sale easSale);
    }
    

    EAS_SaleMapper.xml接口配置文件

    <?xml version="1.0" encoding="UTF8" ?>
    
    
    
    
        
        
            UPDATE QXINTERFACE.SALE_CWJK
            SET
                   sdate=#{sDate},
                   managedeptid=#{manageDeptId},
                   salevalue=#{saleValue},
                   saletaxrate=#{saleTaxRate},
                   flag=#{flag},
                   venderid=#{venderId}
            WHERE shopid=#{shopId} 
        
    
    

    测试代码

    package com.xjbh.mapper;
    
    import com.xjbh.entity.EAS_Sale;
    import com.xjbh.uitls.MyBatisUtil;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.List;
    
    public class EAS_SaleMapperTest {
        @Test
        public void updateEAS_SaleByEAS_SaleTest() {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            EAS_SaleMapper mapper = sqlSession.getMapper(EAS_SaleMapper.class);
            mapper.updateEAS_SaleByEAS_Sale(new EAS_Sale("2021-10-11", "D011", 16, 110.00, 13, 0, 110001));
    
            // CUD语句需要提交事务
            sqlSession.commit();
            sqlSession.close();
        }
    }
    

3.5 Delete

  • id:对应namespace中的方法名

  • parameterType:参数类型,如果参数类型为实体类型,则可以在SQL的参数中访问实体类属性

    EAS_SaleMapper接口类

    package com.xjbh.mapper;
    
    import com.xjbh.entity.EAS_Sale;
    
    import java.util.List;
    
    public interface EAS_SaleMapper {
        int deleteEAS_SaleByShopId(String shopId);
    }
    

    EAS_SaleMapper.xml接口配置文件

    <?xml version="1.0" encoding="UTF8" ?>
    
    
    
    
        
            DELETE FROM QXINTERFACE.SALE_CWJK
            WHERE shopid=#{shopId}
        
    
    

    测试代码

    package com.xjbh.mapper;
    
    import com.xjbh.entity.EAS_Sale;
    import com.xjbh.uitls.MyBatisUtil;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.List;
    
    public class EAS_SaleMapperTest {
        @Test
        public void deleteEAS_SaleByShopIdTest() {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            EAS_SaleMapper mapper = sqlSession.getMapper(EAS_SaleMapper.class);
            mapper.deleteEAS_SaleByShopId("D011");
    
            // CUD语句需要提交事务
            sqlSession.commit();
            sqlSession.close();
        }
    }
    

3.6 如果参数过多,可以使用Map集合较灵活

  • id:对应namespace中的方法名

  • parameterType:参数类型,如果参数类型为实体类型,则可以在SQL的参数中访问实体类属性

    EAS_SaleMapper接口类

    package com.xjbh.mapper;
    
    import com.xjbh.entity.EAS_Sale;
    
    import java.util.List;
    
    public interface EAS_SaleMapper {
        List getSaleListByMap(Map map);
    }
    

    EAS_SaleMapper.xml接口配置文件

    <?xml version="1.0" encoding="UTF8" ?>
    
    
    
    
        
    
    

    测试代码

    package com.xjbh.mapper;
    
    import com.xjbh.entity.EAS_Sale;
    import com.xjbh.uitls.MyBatisUtil;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.List;
    
    public class EAS_SaleMapperTest {
        @Test
        public void getSaleListByMapTest() {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            EAS_SaleMapper mapper = sqlSession.getMapper(EAS_SaleMapper.class);
    
            Map map = new HashMap();
            map.put("mapShopId", "D011");
            List saleList = mapper.getSaleListByMap(map);
    
            for (EAS_Sale eas_sale : saleList) {
                System.out.println(eas_sale);
            }
            sqlSession.close();
        }
    }
    

4. 配置解析

4.1 核心配置文件

MyBatis的配置文件包含了会深深影响MyBatis行为的设置和属性信息。 配置文档的顶层结构如下:

  • configuration(配置)
    • properties(属性)
    • settings(设置)
    • typeAliases(类型别名)
    • typeHandlers(类型处理器)
    • objectFactory(对象工厂)
    • plugins(插件)
    • environments(环境配置)
      • environment(环境变量)
        • transactionManager(事务管理器)
        • dataSource(数据源)
    • databaseIdProvider(数据库厂商标识)
    • mappers(映射器)

4.2 环境配置(environments

MyBatis可以配置成适应多种环境,不过要记住:尽管可以配置多个环境,但每个SqlSessionFactory实例只能选择一种环境。

  • MyBatis默认transactionManager事务管理器类型:JDBC
  • MyBatis默认dataSource 数据源类型:POOLED

4.3 属性(properties

这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的Java属性文件(db.properties)中配置这些属性,也可以在properties元素的子元素中设置

编写一个db.properties属性文件

driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@59.51.66.142:21521:XJBHINFO
username=qxinterface
password=qx$interface#0112

配置核心MyBatis-config.xml文件

<?xml version="1.0" encoding="UTF8" ?>



    
    
    
        
            
            
                
                
                
                
            
        
    
    
    
    
        
    

PS注意:

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

4.4 类型别名(typeAliases

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

类型别名的两种方式

  • 全限定类名指定别名

    核心MyBatis-config.xml文件

    
        
    
    

    EAS_SaleMapper.xml接口配置文件

    <?xml version="1.0" encoding="UTF8" ?>
    
    
    
    
        
    
    
  • 指定一个包名,每一个在包中的Java Bean,在没有注解的情况下,会使用Bean的首字母小写的非限定类名来作为它的别名

    核心MyBatis-config.xml文件

    
        
    
    

    EAS_SaleMapper.xml接口配置文件

    <?xml version="1.0" encoding="UTF8" ?>
    
    
    
    
        
    
    
  • 实体类较少的情况下建议使用第一种,可以DIY别名

  • 实体类较多的情况下建议使用第二种,在不使用注解的情况下不能DIY别名,如若想只用,如下配置

    EAS_Sale实体类

    package com.xjbh.entity;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import org.apache.ibatis.type.Alias;
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Alias("EASSALES")
    public class EAS_Sale {
        private String sDate;
        private String shopId;
        private int manageDeptId;
        private double saleValue;
        private double saleTaxRate;
        private int flag;
        private int venderId;
    }
    

    核心MyBatis-config.xml文件

    
        
    
    

    EAS_SaleMapper.xml接口配置文件

    <?xml version="1.0" encoding="UTF8" ?>
    
    
    
    
        
    
    

4.5 设置(settings

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

设置名 描述 有效值 默认值
cacheEnabled 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 true | false true
lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 true | false false
logImpl 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING 未设置

4.6 映射器(mappers

  • 方法一:使用相对于类路径的资源引用(推荐使用

    
    
      
    
    
  • 方法二:使用映射器接口实现类的完全限定类名

    
    
      
    
    
  • 方法三:将包内的映射器接口实现全部注册为映射器

    
    
      
    
    
  • 注意点:如使用方法二或方法三的情况下,接口和Mapper.xml配置文件必须同名且必须在同一个包下

4.7 作用域(Scope)和生命周期

作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题

  • SqlSessionFactoryBuilder
    • 一旦创建了 SqlSessionFactory,就不再需要它了
    • 最佳作用域是方法作用域(也就是局部方法变量
  • SqlSessionFactory
    • 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例
    • 最佳作用域是应用作用域
  • SqlSession
    • SqlSession 的实例不是线程安全的,因此是不能被共享的
    • 最佳的作用域是请求或方法作用域
    • 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到finally块中

5. ResultMap

ResultMap 元素是 MyBatis 中最重要最强大的元素

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

问题:解决属性名与字段名不一致的情况

EAS_Sale.java实体类

package com.xjbh.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.ibatis.type.Alias;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Alias("EASSALES")
public class EAS_Sale {
    private String sDate;
    private String shopId;
    private int manageDeptId;
    private double saleValue;
    private double saleTaxRate;
    private int flag;
    private int venderId;
}

EAS_SaleMapper.xml配置文件


数据库中的表字段

SELECT sdate, shopId, deptId, saleValues, saleTaxrate, flag, venderId 
FROM QXINTERFACE.SALE_CWJK

结果:会出现类别和销售为空

解决方法:

  • 方法一:对SQL字段名设置别名:

    SELECT sdate, shopId, deptId AS managedeptid, saleValues AS saleValue, saleTaxrate, flag, venderId 
    FROM QXINTERFACE.SALE_CWJK
    
  • 方法二:配置ResultMap即可

    
        
    	
        
        
        
        
        
        
    
    
    
    

6. log4j

6.1 导入pom.xml依赖


  
    org.apache.logging.log4j
    log4j-api
    2.14.1
  
  
    org.apache.logging.log4j
    log4j-core
    2.14.1
  

6.2 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

6.3 配置log4j为日志实现


    

6.4 简单使用

6.4.1 导入Log4j的包

import org.apache.log4j.Logger;

6.4.2 获取一个日志对象,参数为当前类的class

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

6.4.3 常用日志级别(由低到高)

  • DEBUG:指出细粒度信息事件对调试应用程序是非常有帮助的,就是输出debug的信息
  • INFO:表明消息在粗粒度级别上突出强调应用程序的运行过程,就是输出提示信息
  • WARN:表明会出现潜在错误的情形,就是显示警告信息
  • ERROR:指出虽然发生错误事件,但仍然不影响系统的继续运行,就是显示错误信息
  • FATAL:指出每个严重的错误事件将会导致应用程序的退出

7. 分页

7.1 使用SQL LIMIT分页

SELECT * FROM Table LIMIT startIndex, pageSize;

UserMapper接口

public interface AccountMapper {
    List getAccountByLimit(Map map);
}

UserMapper.xml映射


    
    



测试

@Test
public void getAccountByLimitTest() {
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    EAS_SaleMapper mapper = sqlSession.getMapper(AccountMapper.class);

    Map map = new HashMap();
    map.put("startIndex", 0);
    map.put("pageSize", 2);
    List accountList = mapper.getAccountByLimit(map);

    for (Account account : accountList) {
        System.out.println(account);
    }
    sqlSession.close();
}

7.2 使用RowBounds分页

UserMapper接口

public interface AccountMapper {
    List getAccountByRowBounds();
}

UserMapper.xml映射


    
    



测试

@Test
public void getAccountByLimitTest() {
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    RowBounds rowBounds = new RowBounds(0, 2);
    AccountMapper mapper = sqlSession.selectList("com.xjbh.mapper.AccountMapper.getAccountByRowBounds", null, rowBounds);
    
    List accountList = mapper.getAccountByRowBounds();

    for (Account account : accountList) {
        System.out.println(account);
    }
    sqlSession.close();
}

7.3 MyBatis分页插件PageHelper

官网地址:https://pagehelper.github.io/

了解即可

8. 使用注解开发

注解方法:

  • @select(""):查询SQL
  • @insert(""):增加SQL
  • @update(""):修改SQL
  • @delete(""):删除SQL

注解参数:

  • @Param
    • 基本类型或String类型的参数需要加上注解,其余引用类型不需要加
    • 如果只有一个基本类型可以忽略,但建议加上
    • SQL中引用的参数为注解中的参数

UserMapper接口

public interface AccountMapper {
    @select("SELECT id, name, passWord FROM Account WHERE id = #{accId}")
    Account getAccountById(@Param("accId") int id);
}

核心配置文件mybatisc-config.xml

<?xml version="1.0" encoding="UTF8" ?>



    
        
            
            
                
                
                
                
            
        
    
    
    
        
    

测试

@Test
public void getAccountByLimitTest() {
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    AccountMapper mapper = sqlSession.getMapper(AccountMapper.class);
    
    Account account = mapper.getAccountById(1);
    System.out.println(account);
    
    sqlSession.close();
}

9. 多对一处理

9.1 环境搭建

  • pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
        4.0.0
    
        com.xjbh
        MyBatisStudy
        pom
        1.0-SNAPSHOT
        
            MyBatis-02
        
    
        
            
            
                junit
                junit
                4.12
            
            
            
                mysql
                mysql-connector-java
                5.1.6
            
            
            
                app.myoss.cloud.mybatis
                myoss-mybatis
                2.1.7.RELEASE
            
            
            
                org.projectlombok
                lombok
                1.18.20
                provided
            
        
    
        
            
                
                    src/main/resources
                    
                        **/*.properties
                        **/*.xml
                    
                    true
                
                
                    src/main/java
                    
                        **/*.properties
                        **/*.xml
                    
                    true
                
            
        
    
    
  • mybatis-config.xml

    <?xml version="1.0" encoding="UTF8" ?>
    
    
        
    
        
            
        
        
        
            
            
            
        
        
        
            
                
                
                    
                    
                    
                    
                
            
        
    
        
            
        
    
    
  • MyBatisUitl.java

    package com.xjbh.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 MyBatisUtil {
        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();
        }
    }
    
  • POJO

    • Account

      package com.xjbh.pojo;
      
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      
      @Data
      @NoArgsConstructor
      @AllArgsConstructor
      public class Account {
          private int id;
          private String accId;
          private String passWord;
          private String notes;
      }
      
    • Student

      package com.xjbh.pojo;
      
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      
      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      public class Student {
          private Integer id;
          private String name;
          private Teacher teacher;
          private String notes;
      }
      
    • Teacher

      package com.xjbh.pojo;
      
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      
      @Data
      @NoArgsConstructor
      @AllArgsConstructor
      public class Teacher {
          private Integer id;
          private String name;
          private String notes;
      }
      
  • StudentMapper接口

    package com.xjbh.dao;
    
    import com.xjbh.pojo.Student;
    import com.xjbh.pojo.Teacher;
    import org.apache.ibatis.annotations.Param;
    
    import java.util.List;
    
    public interface StudentMapper {
        List getStudentList();
    }
    

9.2 按查询嵌套处理

  • StudentMapper映射

    <?xml version="1.0" encoding="UTF8" ?>
    
    
    
        
            
            
        
        
        
    
    

9.3 按结果嵌套处理

  • StudentMapper映射

    <?xml version="1.0" encoding="UTF8" ?>
    
    
    
        
        
        
            
            
            
            
                
                
                
            
        
    
    

10. 一对多处理

10.1 环境搭建

  • pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
        4.0.0
    
        com.xjbh
        MyBatisStudy
        pom
        1.0-SNAPSHOT
        
            MyBatis-02
        
    
        
            
            
                junit
                junit
                4.12
            
            
            
                mysql
                mysql-connector-java
                5.1.6
            
            
            
                app.myoss.cloud.mybatis
                myoss-mybatis
                2.1.7.RELEASE
            
            
            
                org.projectlombok
                lombok
                1.18.20
                provided
            
        
    
        
            
                
                    src/main/resources
                    
                        **/*.properties
                        **/*.xml
                    
                    true
                
                
                    src/main/java
                    
                        **/*.properties
                        **/*.xml
                    
                    true
                
            
        
    
    
  • mybatis-config.xml

    <?xml version="1.0" encoding="UTF8" ?>
    
    
        
    
        
            
        
        
        
            
            
            
        
        
        
            
                
                
                    
                    
                    
                    
                
            
        
    
        
            
        
    
    
  • MyBatisUitl.java

    package com.xjbh.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 MyBatisUtil {
        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();
        }
    }
    
  • POJO

    • Student

      package com.xjbh.pojo;
      
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      
      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      public class Student {
          private Integer id;
          private String name;
          private Integer tid;
          private String notes;
      }
      
    • Teacher

      package com.xjbh.pojo;
      
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      
      import java.util.List;
      
      @Data
      @NoArgsConstructor
      @AllArgsConstructor
      public class Teacher {
          private Integer id;
          private String name;
          private String notes;
          private List studentList;
      }
      
  • TeacherMapper接口

    package com.xjbh.dao;
    
    import com.xjbh.pojo.Teacher;
    import org.apache.ibatis.annotations.Param;
    
    public interface TeacherMapper {
        Teacher getTeacherById(@Param("tid") Integer id);
    }
    

10.2 按结果嵌套处理

TeacherMapper.xml映射

<?xml version="1.0" encoding="UTF8" ?>



    

    
        
        
        
        
            
            
            
            
        
    

11. 多对一与一对多的总结

  • 关联 - association 【多对一】
  • 集合 - collection 【一对多】
  • javaType & ofType
    • javaType:用来指定实体类中属性的类型
    • ofType:用来指定List或集合中的POJO类型,泛型中的约束类型
  • 注意点:
    • 保证SQL的可读性,尽量保证通俗易懂
    • 注意一对多和多对一中属性名和字段的问题
    • 如果问题不好排查错误,可以使用日志

12. 动态SQL

12.1 什么是动态SQL

根据不同的条件生成不同的SQL代码

12.2 搭建环境

  • pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
        4.0.0
    
        com.com.xjbh
        MyBatisStudy
        pom
        1.0-SNAPSHOT
        
            MyBatis-02
            MyBatis-03
            MyBatis-04
        
    
        
            
            
                junit
                junit
                4.12
            
            
            
                mysql
                mysql-connector-java
                5.1.6
            
            
            
                app.myoss.cloud.mybatis
                myoss-mybatis
                2.1.7.RELEASE
            
            
            
                org.projectlombok
                lombok
                1.18.20
                provided
            
        
    
        
            
                
                    src/main/resources
                    
                        **/*.properties
                        **/*.xml
                    
                    true
                
                
                    src/main/java
                    
                        **/*.properties
                        **/*.xml
                    
                    true
                
            
        
    
    
  • mybatis-config.xml

    <?xml version="1.0" encoding="UTF8" ?>
    
    
        
    
        
            
        
    
        
            
        
        
        
            
                
                
                    
                    
                    
                    
                
            
        
    
        
            
        
    
    
  • MyBatisUtil

    package com.xjbh.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 MyBatisUtil {
        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();
        }
    }
    
  • POJO

    • Student

      package com.xjbh.pojo;
      
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      
      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      public class Student {
          private Integer id;
          private String name;
          private Integer tid;
          private String notes;
      }
      

12.3 IF

  • StudentMapper接口

    package com.xjbh.dao;
    
    import com.xjbh.pojo.Student;
    
    import java.util.List;
    import java.util.Map;
    
    public interface StudentMapper {
        List getStudentByIF(Map map);
    }
    
  • StudentMapper.xml映射

    <?xml version="1.0" encoding="UTF8" ?>
    
    
    
        
    
    
  • 测试代码

    package com.xjbh.dao;
    
    import com.xjbh.pojo.Student;
    import com.xjbh.utils.MyBatisUtil;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class StudentTest {
    
        @Test
        public void getStudentByIFTest() {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
            Map map = new HashMap();
            map.put("id", 2);
            map.put("name", "迪丽热巴");
            List studentList = mapper.getStudentByIF(map);
            for (Student student : studentList) {
                System.out.println(student);
            }
            sqlSession.close();
        }
    }
    

12.4 choosewhenotherwise

  • StudentMapper接口

    package com.xjbh.dao;
    
    import com.xjbh.pojo.Student;
    
    import java.util.List;
    import java.util.Map;
    
    public interface StudentMapper {
        List getStudentByChoose(Map map);
    }
    
  • StudentMapper.xml映射

    <?xml version="1.0" encoding="UTF8" ?>
    
    
    
        
    
    
  • 测试代码

    package com.xjbh.dao;
    
    import com.xjbh.pojo.Student;
    import com.xjbh.utils.MyBatisUtil;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class StudentTest {
    
        @Test
        public void getStudentByChooseTest() {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
            Map map = new HashMap();
            map.put("id", 1);
            map.put("name", "迪丽热巴");
            map.put("notes", "LOL");
            List studentList = mapper.getStudentByChoose(map);
            for (Student student : studentList) {
                System.out.println(student);
            }
            sqlSession.close();
        }
    }
    
  • 注意:从上至下满足其中之一条件后,后续代码就算满足条件也不会执行

12.5 where

  • StudentMapper接口

    package com.xjbh.dao;
    
    import com.xjbh.pojo.Student;
    
    import java.util.List;
    import java.util.Map;
    
    public interface StudentMapper {
        List getStudentByWhere(Map map);
    }
    
  • StudentMapper.xml映射

    <?xml version="1.0" encoding="UTF8" ?>
    
    
    
        
    
    
  • 测试代码

    package com.xjbh.dao;
    
    import com.xjbh.pojo.Student;
    import com.xjbh.utils.MyBatisUtil;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class StudentTest {
        @Test
        public void getStudentByWhereTest() {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
            Map map = new HashMap();
            map.put("id", 1);
            List studentList = mapper.getStudentByWhere(map);
            for (Student student : studentList) {
                System.out.println(student);
            }
            sqlSession.close();
        }
    }
    
  • 总结:WHERE元素只会在子元素返回任何内容的情况下才插入WHERE子句。而且,若子句的开头为ANDORWHERE元素也会将它们去除

12.5 set

  • StudentMapper接口

    package com.xjbh.dao;
    
    import com.xjbh.pojo.Student;
    
    import java.util.List;
    import java.util.Map;
    
    public interface StudentMapper {
        int updateStudentBySet(Map map);
    }
    
  • StudentMapper.xml映射

    <?xml version="1.0" encoding="UTF8" ?>
    
    
    
            UPDATE student
            
                
                    name = #{name},
                
                
                    tid = #{tid},
                
                
                    notes = #{notes},
                
            
            WHERE id = #{id}
        
    
    
  • 测试代码

    package com.xjbh.dao;
    
    import com.xjbh.pojo.Student;
    import com.xjbh.utils.MyBatisUtil;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class StudentTest {
        @Test
        public void getStudentBySetTest() {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
            Map map = new HashMap();
            map.put("notes", "小姐姐");
            map.put("id", 1);
            mapper.updateStudentBySet(map);
            sqlSession.commit();
            sqlSession.close();
        }
    }
    
  • 总结:set元素可以用于动态包含需要更新的列,忽略其它不更新的列

12.6 foreach

  • StudentMapper接口

    package com.xjbh.dao;
    
    import com.xjbh.pojo.Student;
    
    import java.util.List;
    import java.util.Map;
    
    public interface StudentMapper {
        List getStudentByForeach(Map map);
    }
    
  • StudentMapper.xml映射

    <?xml version="1.0" encoding="UTF8" ?>
    
    
    
        
    
    
  • 测试代码

    package com.xjbh.dao;
    
    import com.xjbh.pojo.Student;
    import com.xjbh.utils.MyBatisUtil;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class StudentTest {
        @Test
        public void getStudentByForeach() {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
            Map map = new HashMap();
            ArrayList arrayList = new ArrayList();
            arrayList.add(1);
            arrayList.add(3);
            map.put("idList", arrayList);
            List studentList = mapper.getStudentByForeach(map);
            for (Student student : studentList) {
                System.out.println(student);
            }
            sqlSession.close();
        }
    }
    

13. 缓存

13.1 缓存简介

13.1.1 什么是缓存?

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

13.1.2 为什么使用缓存

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

13.1.3 什么样的数据能使用缓存

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

13.2 MyBatis缓存

  • MyBatis内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制
  • MyBatis系统中默认定义了两级缓存:一级缓存二级缓存
    • 默认情况下,只有一级缓存(SqlSession级别的缓存,也称为本地缓存)
    • 二级缓存需要手动开启和配置,它是基于namespace级别的缓存(Mapper
    • 为了提高扩展性,MyBatis定义了缓存接口Cache,我们可以通过实现Cache接口来自定义二级缓存

13.3 一级缓存

一级缓存也叫本地缓存

  • 与数据库痛一次会话期间查询到的数据会放在本地缓存中
  • 以后如果需要获取相同的数据,直接从缓存中拿,没有必要再去查询数据库

13.4 二级缓存

二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存

  • 基于namespace级别的缓存,一个命名空间,对应一个二级缓存

  • 工作机制

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

    • mybatis-config.xml中配置开启全局缓存

      
          
      
      
    • 在对应的Mapper.xml映射文件中配置

      • eviction:清除策略,默认的清除策略是LRU
        • LRU – 最近最少使用:移除最长时间不被使用的对象
        • FIFO – 先进先出:按对象进入缓存的顺序来移除它们
        • SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象
        • WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象
      • flushInterval:刷新间隔,设置为任意正整数。默认情况是不设置
      • size:引用数目,设置为任意正整数。默认值是 1024
      • readOnly:只读属性,只读的缓存会给所有调用者返回缓存对象的相同实例。默认值是false