前言:Springboot怎么使用想必也無需我多言,Mybitas作為實用性極強的ORM框架也深受廣大開發人員喜愛,有關如何整合它們的文章在網絡上隨處可見。但是今天我會從實戰的角度出發,談談我對二者結合與使用的最佳實踐。
一、依賴與pom
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.4.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.1</version> </dependency> </dependencies>
目前SpringBoot官方的最新版本是2.0.4.RELEASE我們就以這個版本為基礎,2.0以下版本可能會有些區別這里不多解釋。
二、創建配置文件和啟動類
Spring官方推薦使用yml文件,既然是最佳實踐我們就按照官方的要求來做。
application.yml
server:
port: 8090
spring:
datasource:
mimas:
driverClassName: com.mysql.jdbc.Driver
jdbcUrl: jdbc:mysql://192.168.56.101:3306/mimas
username: root
password: 12345678
logging:
level:
com.learnhow.springboot.mybatis.dao: debug
解釋一下三個部分的含義:
(1)server:代表當前服務通過8090端口訪問。
(2)spring:配置了一個名為mimas的數據源,如果項目需要多個數據源可以按照這樣的方式將數據源配置成不同的名稱。
(3)logging:定義dao包下的日志記錄級別為debug,標准輸出會顯示sql語句(這一點對開發還是很重要的)
Application.java
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
三、xml文件與接口
Springboot與Mybatis整合以后可以使用annotation(注解)和xml(配置文件)兩種方式編寫sql語句,我推薦的做法是后者。就目前我接觸到的項目來說,項目部署環境都比較嚴格,往往修改一個BUG到重新部署完成少則2個小時,多則數天。而很多BUG有時候僅僅需要修改幾條SQL語句。如果采用配置文件的方式,這類問題只需要在服務器上修改一下文件然后再重啟一下服務就能完成。其次,我個人也很不喜歡Java代碼和SQL代碼混再一起開發方式,既不美觀也不便於維護。所以通常在項目初期我都會盡量避免這類為以后埋坑的行為。
以下是一個典型的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.learnhow.springboot.mybatis.dao.mimas.UserDao"> <resultMap type="User" id="UserMap"> <id column="id" property="id" jdbcType="BIGINT" /> <result column="user_name" property="username" jdbcType="VARCHAR" /> <result column="user_age" property="age" jdbcType="INTEGER" /> <result column="user_gender" property="gender" jdbcType="INTEGER" /> <result column="ep_id" property="enterpriseId" jdbcType="BIGINT" /> </resultMap> <select id="getAll" resultType="User"> select * from user_t </select> <select id="getOne" resultType="User" parameterType="Long"> select * from user_t t where t.id = #{id} </select> <insert id="saveUsers"> insert into user_t(user_name, user_age, user_gender, ep_id) values <foreach collection="users" item="user" separator=","> (#{user.username}, #{user.age}, #{user.gender} <trim prefix="," suffix=")"> <choose> <when test="user.enterpriseId != null and user.enterpriseId != 0"> #{user.enterpriseId} </when> <otherwise> null </otherwise> </choose> </trim> </foreach> </insert> <update id="modifyEnterpriseId"> update user_t set ep_id = #{eid} where id = #{uid} </update> </mapper>
具體語句和表原型大家不用過分關心,一個mybatis的sql配置文件主要有幾個細節需要注意:
(1)配置文件中的sql語句與dao接口是如何結合的?
實際上mybatis先掃描配置文件然后將sql語句通過namespace和id反向注冊到dao接口中,所以namespace屬性表示接口類的全限定名,每一個方法的id則對應接口類中的每一個接口方法。
(2)查詢中遇到多個參數的情況怎么辦?
如果多個參數都屬於一個單一實體,我們可以直接使用實體對象最為參數。例如配置文件中的兩條select語句。如果實體的屬性名與表的字段明稱不一致可以通過resultMap做關聯。
如果多個參數不屬於單一實體,我們可以在接口方法中通過@Param指定參數的名字然后在語句中使用(參考update方法)。我們應盡量避免在配置文件中使用parameterMap方法和在接口中使用Map對象,因為這樣都不利於大型代碼的維護。
(3)根據情況的不同動態生成SQL語句也是Mybatis的一大亮點,我很喜歡這個特征(參考insert方法)。不過在實際開發中我不並要求開發人員大量使用(任何一種增加編寫難度和提高維護成本的行為都應該被謹慎選擇)。
import java.util.List; import java.util.Set; import org.apache.ibatis.annotations.Param; import com.learnhow.springboot.mybatis.entity.User; public interface UserDao { List<User> getAll(); User getOne(long id); int saveUsers(@Param("users") Set<User> users); int modifyEnterpriseId(@Param("uid") long userId, @Param("eid") long enterpriseId); }
四、Mybatis配置文件
DataSourceConfig.java
import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; @Configuration @MapperScan(basePackages = "com.learnhow.springboot.mybatis.dao.mimas", // 為指定包中的DAO注入SqlSessionTemplate sqlSessionTemplateRef = "mimasSqlSessionTemplate") // 指定SqlSessionTemplate public class DataSourceConfig { @Bean(name = "mimasDataSource") @ConfigurationProperties(prefix = "spring.datasource.mimas") @Primary public DataSource testDataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "mimasSqlSessionFactory") @Primary public SqlSessionFactory testSqlSessionFactory(@Qualifier("mimasDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations( new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/mimas/*.xml")); bean.setTypeAliasesPackage("com.learnhow.springboot.mybatis.entity"); // 指定entity的別名 return bean.getObject(); } @Bean(name = "mimasSqlSessionTemplate") @Primary public SqlSessionTemplate testSqlSessionTemplate( @Qualifier("mimasSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
Springboot的項目都需要配置主數據源,MapperScan表示掃描dao.mimas.*下的所有接口並注入指定的SessionTemplate。下面的三個方法就是產生這個SessionTemplate的過程。
五、事務控制
傳統的方法是在service中做事務控制,我們還是沿用這樣的開發邏輯。
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import com.learnhow.springboot.mybatis.dao.mimas.UserDao; import com.learnhow.springboot.mybatis.entity.User; @Component public class UserService { @Autowired private UserDao userDao; @Transactional public int saveUsers(Set<User> users) { return userDao.saveUsers(users); } @Transactional public void modifyEnterpriseIdByUserId(Set<User> users) { for(User u : users) { userDao.modifyEnterpriseId(u.getId(), u.getEnterpriseId()); } } }
至此,有關Springboot和mybatis的整合我們已經完成。完整代碼由於十分簡單我就不提供鏈接了,有需要幫助的小伙伴可以私信@我。