SpringBoot整合MyBatis

Lou.Chen
大约 9 分钟

@Mapper

@Mapper 相当于由spring容器管理,并映射扫描该接口。

1、为了把mapper这个DAO交給Spring管理,即无需使用**@MapperScan**进行注解扫描此类

2、为了给mapper接口 自动根据一个添加**@Mapper**注解的接口生成一个实现类

  • 需要注意的是:这个接口中不可以定义同名的方法,因为会生成相同的id
  • 也就是说这个接口是不支持重载的

3、如果不使用**@Mapper注解,则需要使用@MapperScan**扫描此接口交由spring管理

4、@Mapper本身包含容器注解

@MapperScan

由spring同一管理扫描

1、扫描接口所在的包的位置

2、@MapperScan(basePackages = "com.mybatis.springbootlcmybatis.dao.mapper")

3、可在接口上不加 @Mapper 和 @Repository

关于xml的使用

1、如果xml在接口的同目录下

​ 放在这里的 UserMapper.xml 会被自动扫描到,但是有另外一个 Maven 带来的问题,就是 java 目录下的 xml 资源在项目打包时会被忽略掉,所以,如果 UserMapper.xml 放在包下,需要在 pom.xml 文件中再添加如下配置,避免打包时 java 目录下的 XML 文件被自动忽略掉:

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

2、如果放在resource目录下

就不用担心打包时被忽略了,必须创建和 Mapper 接口包目录相同的目录层级,这样才能确保打包后 XML 和 Mapper 接口又处于在一起

java--
    mapper--
       SysUserMapper.class
 
resources-- 
    mapper--
       SysUsreMapper.xml

如果不是在同结构目录则:

mybatis.mapper-locations=classpath:mapper/*.xml

如此配置之后,mapper 就可以正常使用了。注意这种方式不需要在 pom.xml 文件中配置文件过滤。

mybatis配置文件详解

1、指定xml文件在resources下的路径映射
mybatis.mapper-locations=classpath:mapper/*.xml
2、执行扫描的基础实体包和mapper接口

直接写接口名和mapper接口名

mybatis:
  type-aliases-package: com.mybatis.springbootlcmybatis.entity,
  						com.mybatis.springbootlcmybatis.dao.mapper
3、执行的sql日志打印到控制台
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

使用PageHelper分页

pagehelper:
  helper-dialect: mysql
  reasonable: true
  support-methods-arguments: true
  params: count=countSql

1、helperDialect:

​ 分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。 你可以配置helperDialect属性来指定分页插件使用哪种方言。

​ 配置时,可以使用下面的缩写值:oracle,mysql,mariadb,sqlite,hsqldb,postgresql,db2,sqlserver,informix,h2,sqlserver2012,derby 特别注意:使用 SqlServer2012 数据库时,需要手动指定为 sqlserver2012,否则会使用 SqlServer2005 的方式进行分页。 ​ 你也可以实现 AbstractHelperDialect,然后配置该属性为实现类的全限定名称即可使用自定义的实现方法。

**2、reasonable:**分页合理化参数,默认值为false。当该参数设置为 true 时,pageNum<=0 时会查询第一页, pageNum>pages(超过总数时),会查询最后一页。默认false 时,直接根据参数进行查询。

**3、supportMethodsArguments:**支持通过 Mapper 接口参数来传递分页参数,默认值false,分页插件会从查询方法的参数值中,自动根据上面 params配置的字段中取值,查找到合适的值时就会自动分页。 使用方法可以参考测试代码中的 com.github.pagehelper.test.basic 包下的ArgumentsMapTestArgumentsObjTest

4、params:为了支持startPage(Object params)方法,增加了该参数来配置参数映射,用于从对象中根据属性名取值, 可以配置 pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值, 默认值为pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero。

官网如何使用分页插件open in new window

其他博客:

(3条消息)Pagehelper分页详解文档 - 平凡的脚步也可以走完伟大的行程 - CSDN博客open in new window

Spring Boot 2.x(十三):你不知道的PageHelper - Vi的技术博客 - 博客园open in new window

注意:

只有紧接着PageHelper.startPage(2,3); 后的那句sql才会进行分页,再下一句sql则不分页。

①使用:

PageHelper.startPage(1, 10);
List<SysUser> allSysUser = sysUserMapper.getAllSysUser();
PageInfo<SysUser> sysUserPageInfo = new PageInfo<>(allSysUser);
PageResult page = PageUtils.getPageResult(sysUserPageInfo);
System.out.println(page.toString());

PageInfo记录了分页的信息 PageHelper设定分页的起始页和页的大小

②从PageInfo<?>(List<?> list) 中获取查询信息

public class PageUtils {

    public static <T> PageResult getPageResult(PageInfo<T> pageInfo) {
        PageResult pageResult = new PageResult();
        pageResult.setPageNum(pageInfo.getPageNum());
        pageResult.setPageSize(pageInfo.getPageSize());
        pageResult.setTotalSize(pageInfo.getTotal());
        pageResult.setTotalPages(pageInfo.getPages());
        /**
         * 获取当前页数的记录数
         */
        pageResult.setContent(pageInfo.getList());
        return pageResult;
    }

}

③定义返回的实体:

public class PageResult {

    /**
     * 页码
     */
    private int pageNum;

    /**
     * 每页的大小
     */
    private int pageSize;

    /**
     * 总记录数
     */
    private long totalSize;

    /**
     * 总页数
     */
    private int totalPages;

    /**
     * 记录模型
     */
    private List<?> content;

}

关于mybatis的逆向工程(代码生成器)

1、代码形式生成:https://blog.csdn.net/testcs_dn/article/details/77881776open in new window
2、图形界面生成:https://github.com/spawpaw/mybatis-generator-gui-extensionopen in new window

mubatis多数据源

1、yml配置文件
# 默认数据源配置
spring:
  datasource:
    url: jdbc:mysql://47.96.141.44:3306/jsptest?useUnicode=true&characterEncoding=utf-8
    password: 147258369
    username: root
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    one:
      url: jdbc:mysql://47.96.141.44:3306/multipleDataSource1?useUnicode=true&characterEncoding=utf-8
      username: root
      password: 147258369
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: com.mysql.cj.jdbc.Driver
    two:
      url: jdbc:mysql://47.96.141.44:3306/multipleDataSource2?useUnicode=true&characterEncoding=utf-8
      username: root
      password: 147258369
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: com.mysql.cj.jdbc.Driver
#    mybatis配置
mybatis:
#                       **注意**                如果配置多数据源 则以下自动配置全部失效 所以需要重新在配置文件config中重新指定
#  扫描resources下的xml文件
#  mapper-locations: classpath:mybatis/**/**/*.xml
#  设置实体的别名 在xml中可直接使用类名
#  type-aliases-package: com.mybatis.springbootlcmybatis.entity
#  设置日志的配置
#                      **此配置也将失效**        请看config中的文件配置
#  configuration:
#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
pagehelper:
  helper-dialect: mysql
  reasonable: true
  support-methods-arguments: true
  params: count=countSql
logging:
  config: classpath:Logback_dev.xml
swagger:
  enable: true
server:
  port: 9002

当使用最新的mysql连接对象:

由driver-class-name: com.mysql.jdbc.Driver ==>driver-class-name: com.mysql.cj.jdbc.Driver

<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <scope>runtime</scope>
</dependency>

当使用其他数据源的bean时,自动配置则失效,需要重新指定SqlSessionFactory和SqlSessionTemplate

2、自定义配置文件:
1、主数据源:

注意: 若使用tk.mybaits 则需要使用tk.mybatis.spring.annotation.MapperScan包下的注解@MapperScan

package com.mybatis.springbootlcmybatis.config;

@Configuration
@MapperScan(basePackages = "com.mybatis.springbootlcmybatis.dao.mapper",sqlSessionFactoryRef = "sqlSessionFactory",sqlSessionTemplateRef = "sqlSessionTemplate")
public class MybatisConfig{

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    DataSource ds() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean bean=new SqlSessionFactoryBean();
        bean.setDataSource(ds());
        org.apache.ibatis.session.Configuration configuration=new org.apache.ibatis.session.Configuration();
        //让自动实现的配置。手动创建生成  StdOutImpl implements Log
        configuration.setLogImpl(StdOutImpl.class);
        bean.setConfiguration(configuration);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/mapper/**/*.xml"));
        bean.setTypeAliasesPackage("com.mybatis.springbootlcmybatis.entity");

        return bean.getObject();
    }
    @Bean
    SqlSessionTemplate sqlSessionTemplate() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory());
    }

}

2、第二数据源:
package com.mybatis.springbootlcmybatis.config;

@MapperScan(basePackages = "com.mybatis.springbootlcmybatis.dao.mapper1",sqlSessionFactoryRef = "sqlSessionFactoryOne",sqlSessionTemplateRef = "sqlSessionTemplateOne")
@Configuration
public class MybatisConfigOne {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.one")
    DataSource dsOne() {
        return DruidDataSourceBuilder.create().build();
    }
    @Bean
    SqlSessionFactory sqlSessionFactoryOne() throws Exception {
        SqlSessionFactoryBean bean=new SqlSessionFactoryBean();
        bean.setDataSource(dsOne());
        org.apache.ibatis.session.Configuration configuration=new org.apache.ibatis.session.Configuration();
        //让自动实现的配置。手动创建生成  StdOutImpl implements Log
        configuration.setLogImpl(StdOutImpl.class);
        bean.setConfiguration(configuration);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/mapper1/**/*.xml"));
        bean.setTypeAliasesPackage("com.mybatis.springbootlcmybatis.entity");
        return bean.getObject();
    }

    @Bean
    SqlSessionTemplate sqlSessionTemplateOne() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactoryOne());
    }
}

3、第三数据源:
注意:

@MapperScan(basePackages = "com.mybatis.springbootlcmybatis.dao.mapperTwo",sqlSessionFactoryRef = "sqlSessionFactoryTwo",sqlSessionTemplateRef = "sqlSessionTemplateTwo")

1、不可在接口上直接加@Mapper这样会导致spring无法准确扫描配对

2、必须在使用@MapperScan扫描的同时将mapper接口和sqlSessionFactoryRef,sqlSessionTemplateRef 同时关联

3、需配置不同的mapper接口和映射的xml。即有多少个数据源就有几套mapper对应的映射

4、注意在resources下的mapper的xml映射文件必须有.xml后缀

5、最后一个大坑,在多数据源配置后,yml/properties中的所有自动配置全部失效,所有的mybatis自动配置需要在config配置的SqlSessionFactoryBean中重新配置包括xml映射,别名,扫描路径,日志输出

tk.myabtis的使用

1、引入依赖
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.0.3</version>
        </dependency>
2、@MapperScan()扫描的时候 使用tk包扫描

import tk.mybatis.spring.annotation.MapperScan;

@MapperScan(basePackages = "com.lc.tkmybatis.dao.mapper")
3、接口继承Mapper
public interface SysUserMapper extends Mapper<SysUser> {}
4、使用
    @Autowired
    private SysUserMapper sysUserMapper;

sysUserMapper.insert() //插入
sysUserMapper.insertSelective(); //有选择的插入 传入的实体中有空属性则不插入该属性

sysUserMapper.delete() //根据实体删除
sysUserMapper.deleteByPrimaryKey() //根据主键删除 注解表示为@id

//有条件的删除
Example example=new Example(SysUser.class);
example.createCriteria().andEqualTo("loginuser", "张三");
sysUserMapper.deleteByExample(example);

//其余类似

Mybatis-Plus的使用

1、引入依赖
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.3.0</version>
    </dependency>
2、注意 不要引入mybatis依赖,不要配置mybatis。因为Mybatis-Plus中有mybatis
3、配置
server:
  port: 9001
spring:
  datasource:
    url: jdbc:mysql://47.96.141.44:3306/hcgnew?useUnicode=true&characterEncoding=utf-8
    username: root
    password: 147258369
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Drivers
logging:
  config: classpath:Logback_dev.xml
mybatis-plus:
  type-aliases-package: com.lc.tkmybatis.entity
  mapper-locations: classpath:mybatis/**/*.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#   源码中默认开启自动转驼峰 this.mapUnderscoreToCamelCase = true;
# 会导致生成的查询自动会有问题 会自动帮我们转换
    map-underscore-to-camel-case: false
4、接口继承
@Repository
public interface SysUserMapper extends BaseMapper<SysUser>{}
public interface SysUserService extends IService<SysUser> {
}
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
}
5、使用
List<SysUser> sysUsers = sysUserMapper.selectList(null); //查询所有

详解:

博客:https://blog.csdn.net/ihtczte/article/details/90216910open in new window

官网:https://mybatis.plus/guide/#%E7%89%B9%E6%80%A7open in new window

自定义通用mapper 批量插入

1、自定义扫描器
package com.mybatis.springbootlcmybatis.config;

@Configuration
//表示在加载完此配置文件后加载本类 @AutoConfigureOrder->指定顺序加载 @AutoConfigureBefore->本类在指定类之前加载
@AutoConfigureAfter(MybatisConfig.class)
public class MyBatisMapperScannerConfig {
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        /**
         * 注入 SqlSessionFactory
         */
        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
        /**
         * 注入 Mapper接口 但是不要扫描到自定义mapper
         */
        mapperScannerConfigurer.setBasePackage("com.mybatis.springbootlcmybatis.dao.mapper");
        /**
         * 注入 自定义mapper
         */
        Properties properties = new Properties();
        /**
         * 通过反射获取路径名  或者直接通过绝对路径 com.mybatis.springbootlcmybatis.core.mybatis.MyMapper
         */
        properties.setProperty("mappers", MyMapper.class.getName());
        properties.setProperty("notEmpty", "false");
        properties.setProperty("IDENTITY", "MYSQL");
        mapperScannerConfigurer.setProperties(properties);
        return mapperScannerConfigurer;
    }
}

2、自定义MyMapper的提供者
package com.mybatis.springbootlcmybatis.config;

import org.apache.ibatis.mapping.MappedStatement;
import tk.mybatis.mapper.entity.EntityColumn;
import tk.mybatis.mapper.mapperhelper.EntityHelper;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import tk.mybatis.mapper.mapperhelper.MapperTemplate;
import tk.mybatis.mapper.mapperhelper.SqlHelper;

import java.util.Set;

/**
 * 继承MapperTemplate
 */
public class MybatisInsertListProvider extends MapperTemplate {

    public MybatisInsertListProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
        super(mapperClass, mapperHelper);
    }

    /**
     * 批量插入 生成xml形式的sql
     *
     * @param ms
     */
    public String insertList(MappedStatement ms) {
        final Class<?> entityClass = getEntityClass(ms);
        StringBuilder sql = new StringBuilder();
        sql.append(SqlHelper.insertIntoTable(entityClass, tableName(entityClass)));
        sql.append(SqlHelper.insertColumns(entityClass, false, false, false));
        sql.append(" VALUES ");
        sql.append("<foreach collection=\"list\" item=\"record\" separator=\",\" >");
        sql.append("<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">");
        Set<EntityColumn> columnList = EntityHelper.getColumns(entityClass);
        for (EntityColumn column : columnList) {
            if (column.isInsertable()) {
                sql.append(column.getColumnHolder("record") + ",");
            }
        }
        sql.append("</trim>");
        sql.append("</foreach>");
        return sql.toString();
    }
}
3、注册自定义Mymapper

在类上@RegisterMapper

或者在配置文件中:

mapper: **mappers: com.mybatis.springbootlcmybatis.core.mybatis.MyMapper **

//注册并扫描该通用mapper  或者直接在配置文件中
// mapper:
//    mappers: com.mybatis.springbootlcmybatis.core.mybatis.MyMapper
@RegisterMapper
public interface MyMapper<T> extends Mapper<T> {
    //特别注意,该接口不能被扫描到,否则会出错
    @InsertProvider(type = MybatisInsertListProvider.class, method = "insertList")
    Integer insertList(List<T> recordList);

}

@InsertProvider: type:提供实现的类 method:实现类中的方法

方法名必须相同. 返回值根据查询的结果返回

4、dao继承自定义MyMapper
public interface StudentMapper extends MyMapper<Student> {
}

5、使用

 @Test
    public void test08(){
        Student student1=new Student();
        student1.setSno("95007");
        student1.setSname("周杰伦");
        student1.setSsex("男");
        student1.setSage("45");
        student1.setSdept("MA");

        Student student2 = new Student();
        student2.setSno("95008");
        student2.setSname("周星驰");
        student2.setSsex("男");
        student2.setSage("55");
        student2.setSdept("MO");

        List<Student> list=new ArrayList<>();
        list.add(student1);
        list.add(student2);


        Integer i = studentMapper.insertList(list);
        System.out.println(i);
    }

博文参考:https://blog.csdn.net/ypp91zr/article/details/89006493open in new window