(五)SpringBoot整合Mybatis通用Mapper
0 Views spring-boot with
本文字数:1,520 字 | 阅读时长 ≈ 7 min

(五)SpringBoot整合Mybatis通用Mapper

0 Views spring-boot with
本文字数:1,520 字 | 阅读时长 ≈ 7 min

SpringBoot整合Thymeleaf、Mybatis

:tada: :tada: :tada: 这里有丰富的 Spring 框架学习案例

仓库地址:spring-learn
欢迎star、fork,给作者一些鼓励

项目介绍

前面我们学习了 SpringBoot整合Mybatis 基础CRUD,这里我们结合上一篇文章实战CRUD业务。

其实之前我已经写过一个SpringBoot整合Mybatis的案例:传送门

技术选型

后端

前端

开发环境

写在前面

如上,前端完全依赖Vue.js,这和传统依赖Jquery的前端区别还是蛮大的,使用Vue即要用基于Node.js的前后端分离的开发模式,而本项目中仅仅是在HTML中引入了vue.js,虽然不是完全的前后端分离开发,但项目中我尽量使用Vue.js渲染数据,涉及后端的也仅是用到Thymeleaf的th:replace拼接页面。看下图:

截图

通用Mapper

开源地址:https://github.com/abel533/MyBatis-Spring-Boot

之前学习了 SpringBoot整合MybatisSpringBoot整合JPA 发现两者各有优缺点,个人而言还是喜欢用Mybatis。

那么虽然Mybatis目前提供了一些注解来简化XML的编写,但是仍需要手动写SQL,相比JPA仍麻烦很多,有没有可以像JPA那样调用Java方法自动生成SQL的办法呢?于是就有了框架:通用Mapper

通用Mapper内置了很多API供开发者调用,目的是简化SQL编写。

mapper generator代码生成器

官方文档:传送门

使用该插件可以方便的生成Entity、Mapper interface、XML

初始化表结构

-- create database springboot_thymeleaf_mybatis charset utf8;

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `username` varchar(255) DEFAULT NULL COMMENT '用户名',
  `password` varchar(255) DEFAULT NULL COMMENT '密码',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `role`;

CREATE TABLE `role` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` varchar(255) DEFAULT NULL COMMENT '名称',
  `description` varchar(255) DEFAULT NULL COMMENT '描述',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `user_role`;

CREATE TABLE `user_role` (
  `user_id` bigint(20) DEFAULT NULL,
  `role_id` bigint(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

按照官方文档首先引入依赖:

<!--mybatis-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.1</version>
</dependency>
<!--mapper-->
<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>1.2.4</version>
</dependency>
<!--pagehelper-->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.3</version>
</dependency> 
<!-- mapper生成依赖 -->
<dependency>
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-core</artifactId>
    <version>1.3.2</version>
    <scope>compile</scope>
    <optional>true</optional>
</dependency>

创建MyMapper.java用于继承tk.mapper(通用Mapper)

public interface MyMapper<T> extends Mapper<T>, MySqlMapper<T> {
}

创建配置文件: /resources/generator/generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>

    <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
        <property name="beginningDelimiter" value="`"/>
        <property name="endingDelimiter" value="`"/>

        <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
            <property name="mappers" value="cn.tycoding.utils.MyMapper"/>
        </plugin>

        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/springboot_thymeleaf_mybatis"
                        userId="root"
                        password="root">
            <property name="nullCatalogMeansCurrent" value="true"/>
        </jdbcConnection>

        <!-- 生成的entity -->
        <javaModelGenerator targetPackage="cn.tycoding.entity" targetProject="spring-boot-thymeleaf-mybatis/src/main/java"/>

        <!-- 生成的Mapper XML-->
        <sqlMapGenerator targetPackage="mapper" targetProject="spring-boot-thymeleaf-mybatis/src/main/resources"/>

        <!-- 生成的Mapper映射类 -->
        <javaClientGenerator targetPackage="cn.tycoding.mapper" targetProject="spring-boot-thymeleaf-mybatis/src/main/java"
                             type="XMLMAPPER"/>

        <table tableName="user"></table>
    </context>
</generatorConfiguration>

注意

生成代码,创建GeneratorDisplay.java

public class GeneratorDisplay {

    public void generator() throws Exception {
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        ConfigurationParser cp = new ConfigurationParser(warnings);
        File configFile = ResourceUtils.getFile("classpath:generator/generatorConfig.xml");
        Configuration config = cp.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);
        for (String warning : warnings) {
            System.out.println(warning);
        }
    }

    public static void main(String[] args) throws Exception {
        try {
            GeneratorDisplay display = new GeneratorDisplay();
            display.generator();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

注意

使用new File("/path")获取到的仅是项目的根路径地址,用其获取new File("generator/generatorConfig")是not found的,要使用Spring提供的ResourceUtils工具类获取项目静态文件路径。

修改generatorConfig.xml<table>的名称,执行GeneratorDisplay.java就能生成不同的文件:

测试

首先需要配置Spring扫描Mapper接口

方式一: 在Mapper接口上添加@Mapper注解

方式二: 在Application.java启动类上添加@MapperScan()注解扫描所有Mapper接口。注意这里的@MapperScan注解来自tk.mybatis.spring.annotation.MapperScan,用spring的会报错。

user表中新增一条记录:

insert into user values (1, 'tycoding', '123', '19');

创建UserMapper.java的测试类UserMapperTest.java:

可以看到,因为UserMapper继承了MyMapper<User>,而MyMapper又继承了Mapper<T>, MySqlMapper<T>。类似Jap中继承JpaRepositoryMapper接口中提供了很多API用于生成SQL,简化SQL编写。

@SpringBootTest
@RunWith(SpringRunner.class)
public class UserMapperTest {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private UserMapper userMapper;

    @Test
    public void findAll() {
        List<User> list = userMapper.selectAll();
        list.forEach(user -> {
            logger.info("user={}", user);
        });
    }

    @Test
    public void findById() {
        User user = userMapper.selectByPrimaryKey(1L);
        logger.info("user={}", user);
    }

    @Test
    public void save() {
        User user = new User();
        user.setUsername("涂陌");
        user.setPassword("123");
        user.setAge(20);
        userMapper.insert(user);
        findAll();
    }

    @Test
    public void update() {
        User user = new User();
        user.setId(2L);
        user.setUsername("小涂陌");
        userMapper.updateByPrimaryKey(user);
        findAll();
    }

    @Test
    public void delete() {
        userMapper.deleteByPrimaryKey(2L);
        findAll();
    }
}

如上,看到这里,感觉和JPA调用接口的方式很像吧,tk.Mapper能帮我们简化很多SQL的编写,但是复杂的SQL还是需要手动写,这点和JPA一样的。

这里我也只是测试了几个常用的CRUD操作,tk.Mapper提供了很多方法,我们通过方法名就能大概猜到,所以这里不再做更多的测试。


交流

以上仅是个人的见解,可能有些地方是错误的,深知自己的菜鸡技术,欢迎大佬指出。

个人建了一个Java交流群:671017003。 欢迎大佬或是新人入驻一起交流学习Java技术。


联系

If you have some questions after you see this article, you can contact me or you can find some info by clicking these links.

如果你觉得这篇文章帮助到了你,你可以帮作者买一杯果汁表示鼓励