Skip to content

SpringBoot & MyBatis 3 & 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

Page Layout Max Width

Adjust the exact value of the page width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the page layout
A ranged slider for user to choose and customize their desired width of the maximum width of the page layout can go.

Content Layout Max Width

Adjust the exact value of the document content width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the content layout
A ranged slider for user to choose and customize their desired width of the maximum width of the content layout can go.