6、Spring Boot 與MyBatis整合
1.6 Spring Boot 與MyBatis整合
簡介
- 詳細介紹如何在Spring Boot中整合MyBatis,並通過註解方式實現對映。
- 完整原始碼:
1.6.1 建立 spring-boot-mybatis 專案
- pom檔案如下
<?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.hw</groupId> <artifactId>spring-boot-mybatis</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-boot-mybatis</name> <description>Demo project for Spring Boot MyBatis</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.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.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> <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>
這裡不引入spring-boot-starter-jdbc依賴,是由於mybatis-spring-boot-starter中已經包含了此依賴
- application.yml 配置資料庫連線
spring: datasource: username: root url: jdbc:mysql://localhost:3306/test password: root driver-class-name: com.mysql.cj.jdbc.Driver
- 建立user表
CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
1.6.2 使用MyBatis註解方式
因為最初設計時,MyBatis 是一個 XML 驅動的框架。配置資訊是基於 XML 的,而且對映語句也是定義在 XML 中的。而到了 MyBatis 3,就有新選擇了。MyBatis 3 構建在全面且強大的基於 Java 語言的配置 API 之上。這個配置 API 是基於 XML 的 MyBatis 配置的基礎,也是新的基於註解配置的基礎。註解提供了一種簡單的方式來實現簡單對映語句,而不會引入大量的開銷。
1.6.2.1 User實體類
package com.hw.springbootmybatis.entity; /** * @Description TODO * @Author hw * @Date 2018/11/19 1:10 * @Version 1.0 */ public class User { private Long id; private String name; private Integer age; // get set 方法 }
1.6.2.2 建立User對映的操作UserMapper
package com.hw.springbootmybatis.mapper; import com.hw.springbootmybatis.entity.User; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; /** * @Description TODO * @Author hw * @Date 2018/11/19 1:14 * @Version 1.0 */ @Mapper public interface UserMapper { @Select("SELECT * FROM USER WHERE NAME = #{name}") User findByName(@Param("name") String name); @Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})") int insert(@Param("name") String name, @Param("age") Integer age); }
1.6.2.3 建立單元測試
package com.hw.springbootmybatis; import com.hw.springbootmybatis.entity.User; import com.hw.springbootmybatis.mapper.UserMapper; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class SpringBootMybatisApplicationTests { @Autowired private UserMapper userMapper; @Test public void contextLoads() { } @Test @Rollback public void findByName() throws Exception { userMapper.insert("AAA", 20); User u = userMapper.findByName("AAA"); Assert.assertEquals(20, u.getAge().intValue()); } }
1.6.2.4 原始碼地址
ofollow,noindex" target="_blank">註解方式原始碼
不幸的是,Java 註解的的表達力和靈活性十分有限。儘管很多時間都花在調查、設計和試驗上,最強大的 MyBatis 對映並不能用註解來構建——並不是在開玩笑,的確是這樣。比方說,C#屬性就沒有這些限制,因此 MyBatis.NET 將會比 XML 有更豐富的選擇。也就是說,基於 Java 註解的配置離不開它的特性。
1.6.3 使用MyBatis XML方式
1.6.3.1 yml檔案:
spring: datasource: username: root url: jdbc:mysql://localhost:3306/test?characterEncoding=utf-8&serverTimezone=GMT%2B8 password: root driver-class-name: com.mysql.cj.jdbc.Driver mybatis: config-location: classpath:mybatis-config.xml mapper-locations: classpath:mapper/*.xml type-aliases-package: com.hw.springbootmybatisxml.entity
1.6.3.2 建立配置檔案mybatis-config.xml
在resource目錄下建立config目錄並建立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> <settings> <setting name="callSettersOnNulls" value="true"/> <setting name="cacheEnabled" value="true"/> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="true"/> <setting name="multipleResultSetsEnabled" value="true"/> <setting name="useColumnLabel" value="true"/> <setting name="useGeneratedKeys" value="false"/> <setting name="autoMappingBehavior" value="PARTIAL"/> <setting name="defaultExecutorType" value="SIMPLE"/> <setting name="mapUnderscoreToCamelCase" value="true"/> <setting name="localCacheScope" value="SESSION"/> <setting name="jdbcTypeForNull" value="NULL"/> </settings> <typeAliases> <typeAlias alias="Integer" type="java.lang.Integer" /> <typeAlias alias="Long" type="java.lang.Long" /> <typeAlias alias="HashMap" type="java.util.HashMap" /> <typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" /> <typeAlias alias="ArrayList" type="java.util.ArrayList" /> <typeAlias alias="LinkedList" type="java.util.LinkedList" /> </typeAliases> </configuration>
1.6.3.3 在resource建立 mapper/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.hw.springbootmybatisxml.mapper.UserMapper"> <resultMap id="BaseResultMap" type="com.hw.springbootmybatisxml.entity.User"> <id column="id" property="id" jdbcType="NUMERIC"/> <result column="name" property="name" jdbcType="VARCHAR"/> <result column="age" property="age" jdbcType="NUMERIC"/> </resultMap> <sql id="Base_Column_List"> id, name, age </sql> <select id="findByName" parameterType="java.lang.String" resultMap="BaseResultMap"> SELECT <include refid="Base_Column_List"/> FROM user WHERE name = #{name} </select> <!--如果涉及多個型別那就必須去掉parameterType; 第二個是#{id}...及後面的引數寫法也是錯誤的, 因為在MyBatis3中不會識別這樣的引數,所以應該改成#{arg0},{arg1}這樣的形式。--> <insert id="insert"> INSERT INTO user (name,age) VALUES (#{arg0}, #{arg1}) </insert> </mapper>
1.6.3.4 User實體類
package com.hw.springbootmybatisxml.entity; /** * @Description TODO * @Author hw * @Date 2018/11/19 1:10 * @Version 1.0 */ public class User { private Long id; private String name; private Integer age; // get set 方法 }
1.6.3.5 建立User對映的操作UserMapper
package com.hw.springbootmybatisxml.mapper; import com.hw.springbootmybatisxml.entity.User; import org.apache.ibatis.annotations.Mapper; /** * @Description TODO * @Author hw * @Date 2018/11/19 1:36 * @Version 1.0 */ @Mapper public interface UserMapper { User findByName(String name); void insert(String name,int age); }
1.6.3.6 建立測試類
package com.hw.springbootmybatisxml; import com.hw.springbootmybatisxml.entity.User; import com.hw.springbootmybatisxml.mapper.UserMapper; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class SpringBootMybatisXmlApplicationTests { @Autowired private UserMapper userMapper; @Test public void contextLoads() { } @Test @Rollback public void findByName() throws Exception { userMapper.insert("ccc", 20); User u = userMapper.findByName("ccc"); Assert.assertEquals(20, u.getAge().intValue()); } }