基于Spring Boot 使用Mybatis + Druid访问MySQL

2,005 阅读5分钟

概述

MyBatis简介

MyBatis是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架,详细介绍可参考官网,其优缺点如下,

MyBatis优点

  • 可以手写SQL,支持编写动态SQL语句(XML中使用if、else),并且手写的SQL容易优化
  • SQL可写在XML里,从程序中彻底分离,降低耦合度
  • 学习成本较低,基本没有学习成本

MyBatis缺点

  • SQL语句编写的工作量较大,尤其是字段多,关联表较多时,不过可以使用mybatis-generate插件解决
  • SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库

MyBatis适用场景

MyBatis专注于SQL本身,试一个足够灵活的DAO层解决方案,对性能要求较高或者需求变化较多的项目,如互联网项目,MyBatis将是不错的选择。

Druid简介

Druid是阿里开源的一个JDBC组件库,包含数据库连接池、SQL Parser等组件,并且内置强大的监控功能,监控特性不影响性能,功能强大,能防止SQL注入,内置Loging能诊断Hack应用行为

项目实战

依赖配置

创建Spring Boot项目,在pom中加入MyBatis、MySQL、Druid依赖,版本version信息详见parent pom,具体代码可参考github

        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>

        <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- druid 连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
        </dependency>

配置文件

application.yml

spring:
  datasource:
    # 数据库驱动
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 数据库地址
    url: 'jdbc:mysql://localhost:3306/test?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8
    &serverTimezone=Asia/Shanghai&useSSL=false'
    username: root
    password: root
    
    druid:
      # 初始化大小、最小或最大
      initial-size: 5
      min-idle: 5
      max-active: 20
      # 获取连接等待超时的时间,单位毫秒
      max-wait: 60000
      # 配置间隔多久进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      time-between-eviction-runs-millis: 60000
      # 配置一个连接在连接池中的最小生存时间,单位是毫秒
      min-evictable-idle-time-millis: 300000
      validation-query: SELECT 1
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      # 打开PSCache,并且制定每个连接上PSCache的大小
      pool-prepared-statements: true
      max-pool-prepared-statement-per-connection-size: 20
      # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,wall用于防火墙
    
mybatis:
  # MyBatis 配置是否开启
  check-config-location: true
  # MyBatis配置文件位置,与check-config-location配合使用
  config-location: classpath:mybatis/mybatis-config.xml
  # mapper 文件存放位置
  mapper-locations: classpath*:mapper/*Mapper.xml

logging:
  level:
    # 日志打印级别,可具体到包、类
    com.kk.domain.mapper: debug

Spring Boot 会自动加载 spring.datasource.* 相关配置,数据源就会自动注入到 sqlSessionFactory 中,sqlSessionFactory 会自动注入到 Mapper 中,对了,你一切都不用管了,直接拿起来使用就行了。

mybatis-config.xml

在src/main/resources/mybatis下创建mybatis-config.xml,该文件是MyBatis的全局配置文件,包含以下几种类型的配置,这些配置必须按以下顺序配置 propertis(属性)、settings(全局配置参数)、typeAliases(类型别名)、typeHandlers(类型处理器)、objectFactory(对象工厂)、plugins(插件)、environments(环境集合熟悉对象)、transactionManager(事务管理)、dataSource(数据源)、mappers(映射器),可到官网查看详细配置

druid配置类

与多数据源或者动态数据源类似,在src/main/java/com/kk/infrastructure/config下定义一个配置类用于接收Druid配置,

@Configuration
public class DataSourceConfig {

    @Value("${spring.datasource.url}")
    private String jdbcUrl;

    @Value("${spring.datasource.username}")
    private String username;

    ... 详细代码可参考github

    @Value("${spring.datasource.druid.max-pool-prepared-statement-per-connection-size}")
    private int maxPoolPreparedStatementPerConnectionSize;

    @Bean
    @Primary // 主数据源
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(jdbcUrl);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setDriverClassName(driverClassName);

        dataSource.setInitialSize(initialSize);
        ... 详细代码可参考github
 dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
        
        return dataSource;
    }

}

创建实体类

使用@Alias注解标识类”别名“,具体代码可参考github,本项目采用DDD目录分层,在src/main/java/com/kk/domain/entity 下创建User POJO类

@Alias("user")
public class User {

    private int id;
    private String userName;
    private String userPassword;

    public User(String userName, String userPassword) {
        this.userName = userName;
        this.userPassword = userPassword;
    }
    
    set、get方法...

Mapper接口类

在src/main/java/com/kk/domain/mapper 下创建UserMapper interface,在类上增加@Mapper注解或者在启动类上增加@MapperScan注解,扫描指定的包就不需要每个mapper增加注解了

@Mapper
public interface UserMapper {

    User findUserByUserName(String userName);

    void updateUserByUserName(User user);

    void deleteUserByUserName(String userName);

    void saveUser(User user);

    List<User> getUserList();
}

Mapper xml配置文件

在src/main/resources/mapper下创建UserMapper.xml 对应UserMapper接口类的方法

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD SQL Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kk.domain.mapper.UserMapper">
    <resultMap id="user" type="com.kk.domain.entity.User"/>
    <parameterMap id="user" type="com.kk.domain.entity.User"/>
    <select id="findUserByUserName" parameterType="String" resultMap="user">
        SELECT * FROM user WHERE user_name = #{1}
    </select>

    <update id="updateUserByUserName" parameterMap="user">
        UPDATE user SET user_password = #{userPassword} WHERE user_name = #{userName}
    </update>

    <delete id="deleteUserByUserName" parameterType="String">
        DELETE FROM user WHERE user_name = #{1}
    </delete>

    <!-- 使用alias自定义的parameterType -->
    <insert id="saveUser" parameterType="user">
        INSERT INTO user (user_password, user_name) VALUES (#{userPassword}, #{userName})
    </insert>

    <select id="getUserList" resultMap="user">
        SELECT * FROM user
    </select>
</mapper>

注:select 标签用于执行查询,多一个resultType用于接收返回类型,resultMap用于建立SQL查询结果字段与实体属性的映射关系

启动类

@SpringBootApplication
public class MyBatisApplication {

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

测试Controller

在src/main/java/com/kk/userinterface.controller下创建UserController类用于测试采用的增加、删除、修改、查询操作,可使用注释的url在浏览起中进行测试

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserMapper userMapper;

    // http://localhost:8071/user/getUser?username=kk
    @RequestMapping("/getUser")
    public String getUser(String username) {
        User user = userMapper.findUserByUserName(username);
        return user != null ? username + " password is " + user.getUserPassword() : "no exist " + username;
    }

    // http://localhost:8071/user/addUser?username=kk&password=123456
    @RequestMapping("addUser")
    public String addUser(String username, String password) {
        User user = new User(username, password);
        userMapper.saveUser(user);
        return "success";
    }

    // http://localhost:8071/user/updateUser?username=kk&password=abc123
    @RequestMapping("/updateUser")
    public String updateUser(String password, String username) {
        User user = new User(username, password);
        userMapper.updateUserByUserName(user);
        return "success";
    }

    // http://localhost:8071/user/deleteUser?username=kk
    @RequestMapping("/deleteUser")
    public String deleteUser(String username) {
        userMapper.deleteUserByUserName(username);
        return "success";
    }

    // http://localhost:8071/user/getUserList
    @RequestMapping("/getUserList")
    public List getUserList() {
        return userMapper.getUserList();
    }
}

示例代码

基于Spring Boot 使用Mybatis + Druid访问MySQL spring-boot-demo