Spring Boot集成Mybatis实现数据库操作

1. 引言

在项目开发中, 我们经常需要使用数据库操作, 而针对Java开发中的数据库持久化技术和框架包括:基础JDBC、JPA、MyBatis、Hibernate等。 近期接手一个项目开发工作, 使用Spring Boot + Mybatis技术进行开发, 现就Spring Boot与Mybatis集成的相关配置与操作记录做一下记录。

1.1 开发环境

  • JDK 1.8
  • Intellij IDEA 2017
  • MySQL 5.1.7
  • Spring Boot 2.0.0.RELEASE
  • MyBatis 3

2. Spring Boot 与 MyBatis 集成配置

1. 创建Spring Boot 项目

使用Intellij Idea中的Spring Initializr创建Spring Boot项目

创建项目

配置项目元数据: 项目包信息、项目名、项目编译打包工具(Maven、Gradle,此处选择Maven)、JDK版本、打包方式(Jar或War)等

配置项目元数据

配置项目所依赖的组件信息,根据项目需要选择相关的项目依赖包, 选择的项目组件包括: Web、JDBC、MySQL和MyBatis等

Web依赖包

SQL、MyBatis依赖包

项目创建完成后, Intellij Idea生成相关的项目文件, 查看生成的Maven依赖文件Pom.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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.garyond.hurricane</groupId>
    <artifactId>info-manager</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>info-manager</name>
    <description>Information Manager project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <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>1.3.2</version>
        </dependency>

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

                <!-- Druid Pool -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.9</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.9</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2. 配置项目application.yml配置文件

Spring Boot支持application.properties和application.yml两种配置文件, 从配置文件的可读性考虑, 项目采用了application.yml配置文件方式, 配置文件中添加数据源连接、MyBatis配置等,如下所示:

# Server Port and Encoding
server:
  port: 9969
  servlet:
    context-path: /infoMgr

# Spring Datasource Settings
spring:
  datasource:
    name: druidDataSource
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://192.168.202.17:3306/auth_service?useUnicode=true&characterEncoding=UTF-8
      username: root
      password: 123456
      filters: stat
      max-active: 100
      initial-size: 1
      max-wait: 60000
      min-idle: 1
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      validation-query: select 'x'
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      pool-prepared-statements: true
      max-open-prepared-statements: 50
      max-pool-prepared-statement-per-connection-size: 20

# Mybatis config
mybatis:
  mapper-locations: classpath:mapping/*.xml
  type-aliases-package: com.garyond.hurricane.infomanager.model

3. 创建项目数据库

配置完项目开发环境后,根据项目整体设计, 创建项目数据库, 如下示例代码:

create database infoMgr;
create table base_user
(
   user_id              varchar(64) not null,
   dept_id              int,
   user_name            varchar(50),
   password             varchar(64),
   real_name            varchar(50),
   phone                varchar(30),
   mobile               varchar(30),
   email                varchar(50),
   create_time          timestamp,
   user_status          int,
   primary key (user_id)
);
... ...

4. 使用 MyBatis Generator自动生成相关的代码

我们在项目pom.xml文件中可以添加MyBatis Generator插件, 并配置Generator插件对应的配置文件${basedir}/src/main/resources/generator/generator.config.xml, 该配置文件用于指定MyBatis下模型、DAO生成的映射包名和位置等信息:

<?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>
    <!-- 数据库驱动:选择你的本地硬盘上面的数据库驱动包-->
    <classPathEntry  location="D:\JarLibrary\mysql-connector-java-5.1.45.jar"/>
    <context id="DB2Tables"  targetRuntime="MyBatis3">
        <commentGenerator>
            <property name="suppressDate" value="true"/>
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <!--数据库链接URL,用户名、密码 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://192.168.202.17/info_manager" userId="info" password="info123">
        </jdbcConnection>
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>
        <!-- 生成模型的包名和位置-->
        <javaModelGenerator targetPackage="com.garyond.hurricane.infomanager.model" targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!-- 生成映射文件的包名和位置-->
        <sqlMapGenerator targetPackage="mapping" targetProject="src/main/resources">
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>
        <!-- 生成DAO的包名和位置-->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.garyond.hurricane.infomanager.dao" targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>
        <!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名-->
        <table tableName="base_user" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
        <table tableName="base_organization" domainObjectName="Department" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
    </context>
</generatorConfiguration>

配置完MyBatis自动代码生成配置文件后,需要在Pom.xml中添加MyBatis Generator相应的依赖包,用于对MyBatis Generator进行自动代码生成。

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>

        <!-- MyBatis Generator -->
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.6</version>
            <configuration>
                <configurationFile>${basedir}/src/main/resources/generator/generator.config.xml</configurationFile>
                <overwrite>true</overwrite>
                <verbose>true</verbose>
            </configuration>
        </plugin>
    </plugins>
</build>

下一步, 在Intellij Idea开发工具中配置Maven运行命令, 如下操作:

配置Maven运行

上图中点Edit Configuration按钮, 进入运行配置界面, 选择左上角的“+”号按钮, 选择Maven插件:

选择Maven运行编译

在弹出的Maven运行配置界面中添加名称和命令行参数mybatis-generator:generate -e

配置名称和参数

完成上述配置后, IntelliJ Idea工具下会生成运行名称, 如下所示:

MyBatis自动代码生成

点击刚配置完成的Table-Generator右边的运行按钮即可执行生成相关的Entity和Dao代码包。

5. 查看生成的代码包

自动生成的MyBatis代码包

User.java

import java.util.Date;

public class User{

    private String userId ;

    private Integer unitId;

    private String unitName;

    private String userName;

    private String password;

    private String realName;

    private String phone;

    private String mobile;

    private String email;

    private Date createTime;

    private Integer userStatus;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public Integer getUnitId() {
        return unitId;
    }

    public void setUnitId(Integer unitId) {
        this.unitId = unitId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName == null ? null : userName.trim();
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password == null ? null : password.trim();
    }

    public String getRealName() {
        return realName;
    }

    public void setRealName(String realName) {
        this.realName = realName == null ? null : realName.trim();
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone == null ? null : phone.trim();
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile == null ? null : mobile.trim();
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email == null ? null : email.trim();
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Integer getUserStatus() {
        return userStatus;
    }

    public void setUserStatus(Integer userStatus) {
        this.userStatus = userStatus;
    }

    public String getUnitName() {
        return unitName;
    }

    public void setUnitName(String unitName) {
        this.unitName = unitName;
    }
}

UserMapper.java

public interface UserMapper {

    int deleteByPrimaryKey(String userId);

    int insert(User record);

    int insertSelective(User record);

    User selectByPrimaryKey(String userId);

    int updateByPrimaryKeySelective(User record);

    int updateByPrimaryKey(User record);
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.garyond.hurricane.infomanager.dao.UserMapper">
  <resultMap id="BaseResultMap" type="com.garyond.hurricane.infomanager.model.User">
    <id column="user_id" jdbcType="VARCHAR" property="userId" />
    <result column="unit_id" jdbcType="INTEGER" property="unitId" />
    <result column="user_name" jdbcType="VARCHAR" property="userName" />
    <result column="password" jdbcType="VARCHAR" property="password" />
    <result column="real_name" jdbcType="VARCHAR" property="realName" />
    <result column="phone" jdbcType="VARCHAR" property="phone" />
    <result column="mobile" jdbcType="VARCHAR" property="mobile" />
    <result column="email" jdbcType="VARCHAR" property="email" />
    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
    <result column="user_status" jdbcType="INTEGER" property="userStatus" />
  </resultMap>
  <sql id="Base_Column_List">
    user_id, unit_id, user_name, password, real_name, phone, mobile, email, 
    create_time, user_status
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from base_user
    where user_id = #{userId,jdbcType=VARCHAR}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.String">
    delete from base_user
    where user_id = #{userId,jdbcType=VARCHAR}
  </delete>
  <insert id="insert" parameterType="com.garyond.hurricane.infomanager.model.User">
    insert into base_user (user_id, unit_id, user_name, 
      password, real_name, phone, 
      mobile, email, 
      create_time, user_status)
    values (#{userId,jdbcType=VARCHAR}, #{unitId,jdbcType=INTEGER}, #{userName,jdbcType=VARCHAR},
      #{password,jdbcType=VARCHAR}, #{realName,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR}, 
      #{mobile,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR}, 
      #{createTime,jdbcType=TIMESTAMP}, #{userStatus,jdbcType=INTEGER})
  </insert>
  <insert id="insertSelective" parameterType="com.garyond.hurricane.infomanager.model.User">
    insert into base_user
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="userId != null">
        user_id,
      </if>
      <if test="unitId != null">
        unit_id,
      </if>
      <if test="userName != null">
        user_name,
      </if>
      <if test="password != null">
        password,
      </if>
      <if test="realName != null">
        real_name,
      </if>
      <if test="phone != null">
        phone,
      </if>
      <if test="mobile != null">
        mobile,
      </if>
      <if test="email != null">
        email,
      </if>
      <if test="createTime != null">
        create_time,
      </if>
      <if test="userStatus != null">
        user_status,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="userId != null">
        #{userId,jdbcType=VARCHAR},
      </if>
      <if test="unitId != null">
        #{unitId,jdbcType=INTEGER},
      </if>
      <if test="userName != null">
        #{userName,jdbcType=VARCHAR},
      </if>
      <if test="password != null">
        #{password,jdbcType=VARCHAR},
      </if>
      <if test="realName != null">
        #{realName,jdbcType=VARCHAR},
      </if>
      <if test="phone != null">
        #{phone,jdbcType=VARCHAR},
      </if>
      <if test="mobile != null">
        #{mobile,jdbcType=VARCHAR},
      </if>
      <if test="email != null">
        #{email,jdbcType=VARCHAR},
      </if>
      <if test="createTime != null">
        #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="userStatus != null">
        #{userStatus,jdbcType=INTEGER},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.garyond.hurricane.infomanager.model.User">
    update base_user
    <set>
      <if test="unitId != null">
        unit_id = #{unitId,jdbcType=INTEGER},
      </if>
      <if test="userName != null">
        user_name = #{userName,jdbcType=VARCHAR},
      </if>
      <if test="password != null">
        password = #{password,jdbcType=VARCHAR},
      </if>
      <if test="realName != null">
        real_name = #{realName,jdbcType=VARCHAR},
      </if>
      <if test="phone != null">
        phone = #{phone,jdbcType=VARCHAR},
      </if>
      <if test="mobile != null">
        mobile = #{mobile,jdbcType=VARCHAR},
      </if>
      <if test="email != null">
        email = #{email,jdbcType=VARCHAR},
      </if>
      <if test="createTime != null">
        create_time = #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="userStatus != null">
        user_status = #{userStatus,jdbcType=INTEGER},
      </if>
    </set>
    where user_id = #{userId,jdbcType=VARCHAR}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.garyond.hurricane.infomanager.model.User">
    update base_user
    set unit_id = #{unitId,jdbcType=INTEGER},
      user_name = #{userName,jdbcType=VARCHAR},
      password = #{password,jdbcType=VARCHAR},
      real_name = #{realName,jdbcType=VARCHAR},
      phone = #{phone,jdbcType=VARCHAR},
      mobile = #{mobile,jdbcType=VARCHAR},
      email = #{email,jdbcType=VARCHAR},
      create_time = #{createTime,jdbcType=TIMESTAMP},
      user_status = #{userStatus,jdbcType=INTEGER}
    where user_id = #{userId,jdbcType=VARCHAR}
  </update>
</mapper>

6. 编写业务逻辑代码及业务展现层

根据业务模型实现各个业务的业务逻辑和业务展现层, 以用户管理为例, 实现用户管理相关的操作逻辑。

用户业务服务接口: UserService.java

public interface UserService {

    public int save(User user);

    public int update(User user);

    public int remove(User user);

    public User getUserById(String userId);

}

用户业务服务实现:UserServiceImpl.java

@Service
public class UserServiceImpl implements UserService{

    @Resource
    private UserMapper userMapper;

    @Resource
    private DepartmentMapper departmentMapper;

    @Override
    public int save(User user) {
        return userMapper.insert(user);
    }

    @Override
    public int update(User user) {
        return userMapper.updateByPrimaryKeySelective(user);
    }

    @Override
    public int remove(User user) {
        return userMapper.deleteByPrimaryKey(user.getUserId());
    }

    @Override
    public User getUserById(String userId) {
        return userMapper.selectByPrimaryKey(userId);
    }
}

用户业务展示:UserController.java

@RestController
@RequestMapping("/user")
public class UserPageController extends BaseController {

    @Autowired
    private UserService userService;

    @RequestMapping(method = RequestMethod.GET)
    public String toPage(Model model) {
        return "userPage";
    }

    /*
     *  删除用户
     */
    @RequestMapping("/create")
    public @ResponseBody JsonResult saveUser(User user) {

        User checkedUser = userService.getUserByUsername(user.getUserName());

        if (null != checkedUser) {
            return this.renderError("用户名:" + user.getUserName() + "已存在");
        }

        checkedUser = userService.getUserByEmail(user.getEmail());

        if (null != checkedUser) {
            return this.renderError("电子邮件:" + user.getEmail() + "已存在");
        }

        checkedUser = userService.getUserByMobile(user.getMobile());

        if (null != checkedUser) {
            return this.renderError("手机号码:" + user.getMobile() + "已存在");
        }

        String passwordDigest = new MD5().getTwiceMD5ofString(user.getPassword());
        user.setPassword(passwordDigest);
        userService.save(user);
        return this.renderSuccess();
    }

    /*
     *  更新用户
     */
    @RequestMapping("/update")
    public @ResponseBody JsonResult updateUser(User user) {

        User checkedUser = userService.getUserById(user.getUserId());
        if (null == checkedUser) {
            return this.renderError("该用户不存在");
        }

        userService.update(user);
        return this.renderSuccess();
    }

    /*
     *  删除用户
     */
    @RequestMapping("/remove")
    public @ResponseBody JsonResult delete(String[] ids) {
        for(String id: ids) {
            userService.removeByUserId(id);
        }
        return this.renderSuccess();
    }
}

7. 在Spring Boot应用启动类中启用MyBatis配置

在启动Spring Boot应用过程中, 需要在启动类中添加@Mapper注解,将MyBatis中的Mapper类路径进行启动加载, 否则MyBatis无法加载相应的数据持久化操作。

package com.garyond.hurricane.infomanager;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.garyond.hurricane.infomanager.dao")
public class InfoManagerApplication {

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

8. 应用测试

完成上述步骤后, 启动Spring Boot应用, 我们可以编写jUnit对相应的业务API接口进行测试, 并且可以通过Postman等工具对应用接口进行测试。 具体测试方法和代码就不在这里一一讲述了。

猜你喜欢

转载自blog.csdn.net/garyond/article/details/80309119