Skip to content

SpringBoot & MyBatis 3 & MySQL

🏷️ Spring Boot MyBatis MySQL

重新整理了一下 MyBatis 的使用,以作备忘。

Eclipse vs IntelliJ IDEA

作为开发的 IDE 来讲我更喜欢用 IntelliJ IDEA ,不过在通过 Maven 运行 MyBatis Generator 插件时,java client 文件(即 Mapper 文件)总是会被覆盖。如果在 Mapper 中增加了自定义的接口定义,重新生成时就没有了。

根据官方文档中的说法,Eclipse 插件会根据方法备注中的 @mbg.generated 标签来识别哪些是自动生成的方法,哪些不是,从而避免自定义的方法被替换掉,但是 IDEA 中貌似没有类似的插件。

没有办法,最好还是通过 Eclipse 来运行 MyBatis Generator。通过 Eclipse 菜单的 HelpEclipse Marketplace 安装 MyBatis Generator 1.4.0 插件。另外因为创建的是 Spring Boot 项目,所以另外还安装了 Spring Tools 4 (aka Spring Tool Suite 4) 插件。

下面是最终使用的配置文件:

mybatis-generator.xml

这里使用了 MapperAnnotationPlugin 插件,貌似是 1.4.0 版本里才有的,如果运行出错的话可以删掉。其对应的功能可以通过在 Application 启动类上添加 @MapperScan("liujiajia.me.mybatis3sample.mapper") 注解来实现。

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>
    <properties resource="mybatis-generator.properties" />
    <context id="TestDB" targetRuntime="MyBatis3">
        <property name="javaFileEncoding" value="UTF-8" />
        <plugin
            type="org.mybatis.generator.plugins.MapperAnnotationPlugin"></plugin>
        <commentGenerator>
            <property name="suppressDate" value="true" />
            <!-- suppressAllComments 为 true 时,多次执行 MyBatis Generator 会生成重复的代码 -->
            <!-- <property name="suppressAllComments" value="true"/> -->
            <property name="addRemarkComments" value="true" />
        </commentGenerator>
        <jdbcConnection driverClass="${test.driver}"
            connectionURL="${test.url}" userId="${test.username}"
            password="${test.password}">
        </jdbcConnection>
        <javaTypeResolver>
            <property name="forceBigDecimals" value="true" />
        </javaTypeResolver>
        <!-- generate Model -->
        <javaModelGenerator
            targetPackage="${javaModelGenerator.targetPackage}"
            targetProject="${javaModelGenerator.targetProject}">
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
        <!-- 自动生成xml -->
        <sqlMapGenerator
            targetPackage="${sqlMapGenerator.targetPackage}"
            targetProject="${sqlMapGenerator.targetProject}">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>
        <!-- 自动生成mapper接口, 可以是 ANNOTATEDMAPPER(注解), XMLMAPPER(xml), MIXEDMAPPER -->
        <javaClientGenerator type="XMLMAPPER"
            targetPackage="${javaClientGenerator.targetPackage}"
            targetProject="${javaClientGenerator.targetProject}">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>
        <table tableName="country">
        </table>
    </context>
</generatorConfiguration>

mybatis-generator.properties

部分配置是放在 mybatis-generator.properties 文件中的,示例如下:

properties
test.driver=com.mysql.cj.jdbc.Driver
test.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC
test.username=root
test.password=root

javaModelGenerator.targetPackage=liujiajia.me.mybatis3sample.model
javaModelGenerator.targetProject=MyBatisSample/src/main/java
sqlMapGenerator.targetPackage=liujiajia.me.mybatis3sample.mapper
sqlMapGenerator.targetProject=MyBatisSample/src/main/resources
javaClientGenerator.targetPackage=liujiajia.me.mybatis3sample.mapper
javaClientGenerator.targetProject=MyBatisSample/src/main/java

关于 targetProject 的值,在 IDEA 中是不需要带上项目名(MyBatisSample)的,在 Eclipse 中需要加上去,否则会报找不到 src 项目的错误(Eclipse 用的少,不确定是不是哪边配置不对导致的)。
另外 sqlMapGeneratorjavaClientGeneratortargetPackage 貌似一定要一致,否则运行时会报错。

运行 MyBatis Generator 插件

右键 mybatis-generator.xml 然后选择 Run AsRun MyBatis Generator。生成的代码根据 targetRuntime 的不同会有很大的不同,这里就不贴了。

项目代码

这部分是项目中使用到的 Maven 配置文件等。

pom.xml

因为用到了 Swagger-UI ,所以添加了 springfox-swagger-uispringfox-swagger2 包。

数据库是 MySQL,需要添加 mysql-connector-java 包。

plugins 中还配置了 mybatis-generator-maven-plugin 插件,不过如果只通过 Eclipse 中的插件来生成的话,这段配置就用不到了。

xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>liujiajia.me</groupId>
    <artifactId>mybatis3sample</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mybatis3sample</name>
    <description>Demo project for MyBatis3</description>

    <properties>
        <java.version>1.8</java.version>
        <swagger.version>2.9.2</swagger.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${swagger.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${swagger.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.5</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.4.0</version>
                <dependencies>
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>8.0.20</version>
                    </dependency>
                    <dependency>
                        <groupId>org.mybatis.generator</groupId>
                        <artifactId>mybatis-generator-core</artifactId>
                        <version>1.4.0</version>
                    </dependency>
                    <dependency>
                        <groupId>org.mybatis</groupId>
                        <artifactId>mybatis</artifactId>
                        <version>3.2.4</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <!--允许移动生成的文件 -->
                    <verbose>true</verbose>
                    <!-- 是否覆盖 -->
                    <overwrite>true</overwrite>
                    <!-- 自动生成的配置 -->
                    <configurationFile>src/main/resources/mybatis-generator.xml</configurationFile>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

applicationContext.xml

这里是代码中需要用到的配置文件,在启动文件中指定。

xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--数据源-->
    <bean id="dataSource"
          class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
    <!--Sql Session Factory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>
</beans>

Mybatis3sampleApplication.java

上面提到过如果 MapperAnnotationPlugin 插件找不到的话,可以在这里通过添加 @MapperScan("liujiajia.me.mybatis3sample.mapper") 注解的方式来实现相同的功能。

java
package liujiajia.me.mybatis3sample;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@SpringBootApplication
@ImportResource("classpath:applicationContext.xml")
@EnableSwagger2
public class Mybatis3sampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(Mybatis3sampleApplication.class, args);
    }
}

CountryController.java

这是一个默认的示例,可以用来做参考。

java
package liujiajia.me.mybatis3sample.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import liujiajia.me.mybatis3sample.mapper.CountryMapper;
import liujiajia.me.mybatis3sample.model.Country;
import liujiajia.me.mybatis3sample.model.CountryExample;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

@Api(tags = { "国家操作接口" })
@RestController
@RequestMapping("api/country")
public class CountryController {
    @Resource
    private CountryMapper mapper;

    @ApiOperation(value = "根据主键获取国家信息", notes = "接口备注信息")
    @RequestMapping(value = "pk/{id}", method = RequestMethod.GET)
    public Country findByPrimaryKey(@PathVariable("id") int id) {
        return mapper.selectByPrimaryKey(id);
    }

    @ApiOperation(value = "根据主键获取国家信息(自定义 Mapper 方法)", notes = "接口备注信息(自定义 Mapper 方法)")
    @RequestMapping(value = "customize/{id}", method = RequestMethod.GET)
    public Country findById(@PathVariable("id") int id) {
        return mapper.findById(id);
    }

    @ApiOperation(value = "根据主键获取国家信息(Example)", notes = "接口备注信息(Example)")
    @RequestMapping(value = "example/{id}", method = RequestMethod.GET)
    public List<Country> findByExample(@PathVariable("id") int id) {
        CountryExample example = new CountryExample();
        example.createCriteria().andIdEqualTo(id);
        return mapper.selectByExample(example);
    }
}

官方示例 是通过 sqlSession.getMapper 方法来获取 Mapper 实例的,不过我感觉通过 @Resource 注解的方式也挺方便的。

java
SqlSession sqlSession = sqlSessionFactory.openSession();

try {
    MyTableMapper mapper = sqlSession.getMapper(MyTableMapper.class);
    List<MyTable> allRecords = mapper.selectByExample(null);
} finally {
    sqlSession.close();
}

time zone 错误

连接 MySQL 数据库时报如下错误:

Failed to execute goal org.mybatis.generator:mybatis-generator-maven-plugin:1.3.5:generate (default-cli) on project mybatis3sample: The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.

Description:

Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine a suitable driver class

urljdbc:mysql://localhost:3306/test 后面添加 ?serverTimezone=UTC 就好了。

参考

  1. MyBatis-Spring SqlSession:之前写的一篇博客
  2. Spring Initializr:可以很方便的初始化一个 Spring 项目代码
  3. Mvn Repository:查询 Maven 依赖的网站
  4. MySQL 的 driverClassName、url
  5. github/gitignore:包含常用的开发语言、IDE 对应的 .gitignore 文件的常规写法
  6. Mybatis Generator 生成代码重复
  7. eclipse 集成 MybatisGenerator 及使用
  8. MyBatis Generator Generated Java Client Objects