前言
整合Mybtis對於Spring Boot來說,是非常簡單的, 通過這一篇文章, 你可以無壓力快速入門,不過開始之前我要說一下我的版本信息:
maven 3.2.5
jdk 1.8
Spring Boot 2.1.6
創建項目
依然是使用idea的自動化配置, 不過這裏,我們需要勾選以下依賴:
如果你勾選了 MyBatis , 你會發現你的pom文件裏有 :
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.0</version> </dependency>
這條依賴
只要是帶 *-spring-boot-starter的,都是Spring Boot官方推薦的, 這裏的mybatis就是, 讓我們來看一下mybatis包下的所有包:
我們發現它引入了, mybatis-spring 的包等等,以及還有mybatis-spring-boot-autoconfigure, 這個是自動配置的意思, 對於Spring Boot來說,自動配置是一大特點
配置Druid數據源
Spring Boot2.x的數據源 hikari 的, 而1.x則是 Tomcat的, 所以我們要配置以下自己的數據源
<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 等等同級的,哦對了, 如果你是 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 的類似映射。
再次試驗:
可以看出已經成功了
無論是哪種版本. 要根據自己的實際情況來定, 註解雖然方便, 但是複雜業務的就不行了