Spring Boot-甜蜜的整合MyBatis&注解方式&配置方式

前言

建军节快乐各位~
我的博客: aaatao66.github.io/php

掘金: juejin.im/user/5d1873…css

优先更新我的博客, 其次是掘金。java

整合Mybtis对于Spring Boot来讲,是很是简单的, 经过这一篇文章, 你能够无压力快速入门,不过开始以前我要说一下个人版本信息:mysql

  • maven 3.2.5
  • jdk 1.8
  • Spring Boot 2.1.6

建立项目

依然是使用idea的自动化配置, 不过这里,咱们须要勾选如下依赖:git

若是你勾选了 MyBatis , 你会发现你的pom文件里有 :github

<dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>
复制代码

这条依赖web

只要是带 *-spring-boot-starter的,都是Spring Boot官方推荐的, 这里的mybatis就是, 让咱们来看一下mybatis包下的全部包:spring

咱们发现它引入了, mybatis-spring 的包等等,以及还有mybatis-spring-boot-autoconfigure, 这个是自动配置的意思, 对于Spring Boot来讲,自动配置是一大特色sql

配置Druid数据源

Spring Boot2.x的数据源 hikari 的, 而1.x则是 Tomcat的, 因此咱们要配置如下本身的数据源数据库

个人上一篇文章介绍了Druid: aaatao66.github.io/2019/07/30/…

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>
复制代码

引入这个依赖就行了

而后在 application.yml 配置文件下:

spring:
 datasource:
 password: root
 username: root
 url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC
 driver-class-name: com.mysql.cj.jdbc.Driver
 type: com.alibaba.druid.pool.DruidDataSource

 initialSize: 5
 minIdle: 5
 maxActive: 20
 maxWait: 60000
 timeBetweenEvictionRunsMillis: 60000
 minEvictableIdleTimeMillis: 300000
 validationQuery: SELECT 1 FROM DUAL
 testWhileIdle: true
 testOnBorrow: false
 testOnReturn: false
 poolPreparedStatements: true
    # 配置监控统计拦截的filters,去掉后监控界面sql没法统计,'wall'用于防火墙
 filters: stat,wall,log4j
 maxPoolPreparedStatementPerConnectionSize: 20
 useGlobalDataSourceStat: true
 connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
复制代码

我在上一篇文章说过, 下面这一堆的属性是不生效的, 若是想要生效, 须要特殊配置一下, 而且我把上一章说的 Druid监控也配置了:

package com.carson.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class DruidConfig {

    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource druid() {
        return new DruidDataSource();
    }

    // 配置 Druid 监控
    //1) 配置一个管理后台的Servlet
    @Bean
    public ServletRegistrationBean statViewServlet() {
        ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        Map<String, String> initParams = new HashMap<>();
        // 这里是 druid monitor(监视器)的 帐号密码, 能够任意设置
        initParams.put("loginUsername", "admin");
        initParams.put("loginPassword", "123456");
        initParams.put("allow", "");
        initParams.put("deny", "192.123.11.11");
        // 设置初始化参数
        bean.setInitParameters(initParams);
        return bean;
    }

    // 2)配置一个监控的 filter
    @Bean
    public FilterRegistrationBean webStatFilter() {
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new WebStatFilter());

        Map<String, String> initParams = new HashMap<>();
        initParams.put("exclusions","*.js,*.css,/druid/*");

        bean.setInitParameters(initParams);

        bean.setUrlPatterns(Arrays.asList("/*"));
        return bean;
    }
}
复制代码

启动主类, 查看是否能够进入到 德鲁伊监视器, 若是你报错了请添加 log4j 依赖:

<dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
<!--我也不清楚为何, 不加log4j的话就会报错-->
复制代码

查看效果:

利用SpringBoot建表

而后在 resources/sql 下引入两个建表的sql文件:

  • department.sql:
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for department
-- ----------------------------
DROP TABLE IF EXISTS `department`;
CREATE TABLE `department` (
  `id`             INT(11) NOT NULL AUTO_INCREMENT,
  `departmentName` VARCHAR(255)     DEFAULT NULL,
  PRIMARY KEY (`id`)
)
  ENGINE = InnoDB
  AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8;
复制代码
  • employee.sql:
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for employee
-- ----------------------------
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
  `id`       INT(11) NOT NULL AUTO_INCREMENT,
  `lastName` VARCHAR(255)     DEFAULT NULL,
  `email`    VARCHAR(255)     DEFAULT NULL,
  `gender`   INT(2)           DEFAULT NULL,
  `d_id`     INT(11)          DEFAULT NULL,
  PRIMARY KEY (`id`)
)
  ENGINE = InnoDB
  AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8;
复制代码

而且在 application.yml 文件下写入:

 schema:
 - classpath:sql/department.sql
 - classpath:sql/employee.sql
 initialization-mode: always  
复制代码

schema`是与 password/username 等等同级的, 若是你不懂yml文件与properties的区别, 那么你能够看我之前的文章: aaatao66.github.io/2019/06/30/…

哦对了, 若是你是 springboot 2.x版本以上的, 你可能须要加上initialization-mode这个属性。

运行主类, 查看是否建表成功, 个人数据库中已经生成了这两张表,这里我就不截图了

若是你的程序在设置sql文件后 启动报错了:

  • 重启 idea (重启大法好啊!)

  • 查看 schema是否配置对了 sql文件的名字

  • schema:

    ​ -(空格)classpath:sql/xxx.sql

    注意格式

对应数据库实体类

  • Employee.java
package com.carson.domain;

public class Employee {

    private Integer id;
    private String lastName;
    private Integer gender;
    private String email;
    private Integer dId;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getdId() {
        return dId;
    }

    public void setdId(Integer dId) {
        this.dId = dId;
    }
}

复制代码
  • Department.java
package com.carson.domain;

public class Department {
    private Integer id;
    private String departmentName;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getDepartmentName() {
        return departmentName;
    }

    public void setDepartmentName(String departmentName) {
        this.departmentName = departmentName;
    }
}

复制代码

记得把刚才我配置文件的 schema属性所有注释掉, 咱们不但愿下次运行的时候会再次建立表

数据库交互

- 注解版

  • 创建一个 Mapper, 把sql语句直接写在上面
package com.carson.mapper;

import com.carson.domain.Department;
import org.apache.ibatis.annotations.*;

// 指定这是一个 mapper
@Mapper
public interface DepartmentMapper {

    @Select("select * from department where id=#{id}")
    public Department getDepById(Integer id);

    @Delete("delete from department where id=#{id}")
    public int deleteDepById(Integer id);

    @Insert("insert into department(departmentName) values(#{departmentName})")
    public int insertDept(Department department);

    @Update("update department set departmentName=#{departmentName} where id=#{id}")
    public int updateDept(Department department);
}
复制代码

而后写一个Controller :

package com.carson.controller;

import com.carson.domain.Department;
import com.carson.mapper.DepartmentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController // 表明返回 json 数据的 controller
public class DeptController {

    @Autowired
    DepartmentMapper departmentMapper;

    @GetMapping("/dept/{id}")
    public Department getDept(@PathVariable("id") Integer id) {
        return departmentMapper.getDepById(id);
    }

    @GetMapping
    public Department inserDept(Department department) {
        departmentMapper.insertDept(department);
        return department;
    }

}
复制代码
  • 经过 @PathVariable 能够将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符能够经过@PathVariable(“xxx“) 绑定到操做方法的入参中。

启动主类, 输入这个: localhost:8080/dept?departmentName=AA , 这是往数据库增长一条数据:

而后查询: localhost:8080/dept/3 , 我数据库id是3, 因此我要查询3:

不过发现一个问题, 在插入数据的时候获取不到 id:

因此咱们要使用一个@Options注解:

@Options(useGeneratedKeys = true,keyProperty = "id")
    @Insert("insert into department(departmentName) values(#{departmentName})")
    public int insertDept(Department department);
复制代码

添加到刚才 mapper中insert 的 @value注解上面

  • useGeneratedKeys : 使用生成的主键
  • keyProperty: 意思是 Department 里面的哪一个属性是主键, 就是咱们的 id

试着插入一条数据:

我以前在文章里写了,可是实际忘记注释掉 schema , 致使每次运行都会从新建立数据库, 各位要注意

还有一个问题

咱们把数据库的字段名改为 department_name 而实体类是departmentName;

而且把sql语句也改正

@Options(useGeneratedKeys = true,keyProperty = "id")
    @Insert("insert into department(department_name) values(#{departmentName})")
    public int insertDept(Department department);

    @Update("update department set department_name=#{departmentName} where id=#{id}")
    public int updateDept(Department department);
复制代码

而后在进行查询操做的话:

咱们发现获取不到 departmentName 了, 之前Spring 咱们是使用配置文件来应对这种状况的, 可是咱们如今没有了xml文件,咱们该怎么办呢?

世上无难事

建立自定义配置类:

package com.carson.config;

import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBatisConfig {

    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
        return new ConfigurationCustomizer() {
            @Override
            public void customize(org.apache.ibatis.session.Configuration configuration) {
                configuration.setMapUnderscoreToCamelCase(true);
            }
        };
    }
}
复制代码

注意这里面的 setMapUnderscoreToCamelCase,意思是:

翻译大法好啊, 个人英文太差了, 再次访问 http://localhost:8080/dept/1 查询操做, 我发现已经不是 null了:

{"id":1,"departmentName":"jackMa"}
复制代码

马总正确的展示出来了!

MapperScan注解

扫描器, 用来扫描mapper接口的

我把它标记到 启动类 上(你能够标记在任何地方):

指定一个包,它会扫描这个包下全部的 mapper 接口, 防止你的mapper文件太多, 而且忘记加 @mapper 注解, 这样能够提升正确性

- 配置文件版

注解版貌似很方便, 可是若是遇到复杂的sql , 好比动态sql等等, 仍是须要用 xml 配置文件的;

建立一个 Employee 的Mapper接口:

package com.carson.mapper;

import com.carson.domain.Employee;

public interface EmployeeMapper {

    public Employee getEmpById(Integer id);

    public void insertEmp(Employee employee);

}

复制代码

在 resources/mybatis 下建立一个 mybatis-config.xml 全局配置文件:

<?xml version="1.0" encoding="UTF-8" ?>
        <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

</configuration>
复制代码

在 resources/mybatis/mapper 包下建立 EmployeeMapper.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">

<!-- 绑定接口 而且写两条 SQL 语句-->
<mapper namespace="com.carson.mapper.EmployeeMapper">

    <select id="getEmpById" resultType="com.carson.domain.Employee">
    select * from employee where id = #{id}
  </select>

    <insert id="insertEmp">
        insert into employee(lastName,email,gender,d_id) values (#{lastName},	  		#{email},#{gender},#{d_id})
    </insert>
</mapper>
复制代码

而后再 application.yml 配置文件下添加一条配置:

# mybatis属性是跟 spring 属性平级的, 千万不要把格式搞错
mybatis:
# 指定全局配置文件
 config-location: classpath:mybatis/mybatis-config.xml
# 指定 mapper 映射文件, * 表明全部 
 mapper-locations: classpath:mybatis/mapper/*.xml
复制代码

让咱们在刚才的DeptController类里添加一段 Controller :

@Autowired
    EmployeeMapper employeeMapper
    
    @GetMapping("emp/{id}")
    public Employee getEmp(@PathVariable("id") Integer id) {
        return employeeMapper.getEmpById(id);
    }
复制代码

启动主类访问一下 localhost:8080/emp/1 , 查看结果:

咱们发现 dId没有查询出来, 这是由于 数据库字段是 d_id , 而java里是 dId , 因此咱们要像刚才注解版同样, 配置同样东西, 让咱们打开 mapper全局配置文件添加:

<?xml version="1.0" encoding="UTF-8" ?>
        <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
</configuration>
复制代码

mapUnderscoreToCamelCase : 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的相似映射。

再次试验:

能够看出已经成功了

不管是哪一种版本. 要根据本身的实际状况来定, 注解虽然方便, 可是复杂业务的就不行了


再见,谢谢~

相关文章
相关标签/搜索