SpringBoot | 第三十五章:Mybatis的整合和使用
前言
最近收到公眾號留言說,單純的
Mybatis
的整合和使用。前面在第九章:Mybatis-plus的整合和使用介紹了基於mybatis-plus
的整合和使用。後者也只是對mybatis
進行了功能增強,原本的用法都是沒有變化的。那今天就來簡單介紹瞭如何springboot
中如何整合和使用Mybatis
吧。
SpringBoot的整合和使用
MyBatis
是一款優秀的持久層框架,它支援定製化SQL、儲存過程以及高階對映。MyBatis
避免了幾乎所有的 JDBC 程式碼和手動設定引數以及獲取結果集。MyBatis
可以使用簡單的XML或
註解來配置和對映原生資訊,將介面和Java的POJOs(Plain Old Java Objects,普通的 Java物件)對映成資料庫中的記錄。
這裡介紹基於xml
和註解
兩種方式進行配置。同時使用mybatis-spring-boot-starter
進行整合。
這裡選用的mybatis-spring-boot-starter版本為:
1.3.2
。 對應Mybatis版本為:3.4.6
通用配置
兩種方式都引入一下的pom
配置:
<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> </dependency>
這裡以user
表為例子,資料庫為mysql
DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` bigint(20) DEFAULT NULL COMMENT '唯一標示', `code` varchar(20) DEFAULT NULL COMMENT '編碼', `name` varchar(64) DEFAULT NULL COMMENT '名稱', `status` char(1) DEFAULT '1' COMMENT '狀態 1啟用 0 停用', `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間', `gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時間' ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
實體類User
為:
/**
* <p>
*
* </p>
*
* @author oKong
* @since 2018-12-02
*/
@Data
@Accessors(chain = true)
public class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1779270373648636358L;
/**
* 唯一標示
*/
private Long id;
/**
* 編碼
*/
private String code;
/**
* 名稱
*/
private String name;
/**
* 狀態1 啟用 0 停用
*/
private StatusEnum status;
/**
* 建立時間
*/
private Date gmtCreate;
/**
* 修改時間
*/
private Date gmtModified;
}
狀態列舉類StatusEnum
:
public enum StatusEnum {
DISABLE,
ENABLE;
}
配置檔案:application.properties
# 實體別名
mybatis.type-aliases-package=cn.lqdev.learning.springboot.chapter35.biz.entity
# 資料庫配置
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/learning?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=
spring.profiles.active=anno
啟動類
/**
* mybaits整合
* @author oKong
*
*/
@SpringBootApplication
@Slf4j
public class MybatisApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(MybatisApplication.class, args);
log.info("spring-boot-mybatis-chapter35啟動!");
}
}
註解方式
0.建立註解版的mapper:
UserMapper.java
/**
* 註解配置
* @author okong
*
*/
public interface UserMapper {
//配置返回的欄位型別,這裡配置了建立日期和修改日期自動
@Select("select * from user where id = #{id}")
@Results({
@Result(column = "gmt_create",property = "gmtCreate",jdbcType=JdbcType.DATE),
@Result(column = "gmt_modified",property = "gmtModified",jdbcType=JdbcType.DATE)
})
User queryOne(Long id);
// 列舉類 預設是使用 EnumTypeHandler 處理類,即使用列舉name作為值
//status 為列舉類 也可以直接指定了 typeHandler類 作為處理類 ,如:#{status,typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}
//還可以在sqlFactory 直接使用 TypeHandlerRegistry 進行註冊 詳看;MybatisConfig 類
//最簡單:自定義 ConfigurationCustomizer 了進行設定 詳看;MybatisConfig 類
@Insert("insert into user(code,name,status) values(#{code},#{name}, #{status})")
//以下配置會對user物件進行id賦值
@Options(keyProperty="id",keyColumn="id",useGeneratedKeys=true)
int insert(User user);
@Update("update user set code=#{code}, name = #{name}, status = #{status} where id=#{id}")
void update(User user);
@Delete("delete from user where id=#{id}")
void delete(Long id);
@Select("select * from user where code = #{code}")
@Results({
@Result(column = "gmt_create",property = "gmtCreate",jdbcType=JdbcType.DATE),
@Result(column = "gmt_modified",property = "gmtModified",jdbcType=JdbcType.DATE)
})
List<User> queryByParams(@Param("code")String code);
}
簡單對以上相關注解進行說明下:
- @Select 是查詢類的註解,所有的查詢均使用這個
- @Result 修飾返回的結果集,關聯實體類屬性和資料庫欄位一一對應,如果實體類屬性和資料庫屬性名保持一致,就不需要這個屬性來修飾。
- @Insert 插入資料庫使用,直接傳入實體類會自動解析屬性到對應的值
- @Update 負責修改,也可以直接傳入物件
- @delete 負責刪除
- @Options 對映語句的屬性,如新增時需要返回自增的ID時:
@Options(keyProperty="id",keyColumn="id",useGeneratedKeys=true)
具體的可以去官網查閱:http://www.mybatis.org/mybatis-3/zh/java-api.html
2.指定mapper掃描包路徑,使用註解@MapperScan
/**
* mybaits配置
* @author oKong
*
*/
@Configuration
@MapperScan("cn.lqdev.learning.springboot.chapter35.biz.mapper")//mapper地址
public class MybatisConfig {
}
注意:若使用Druid
進行資料連線池管理,也可以在此類中進行DataSource
的相關配置。
3.編寫測試類進行測試。
/**
* 測試類
* @author oKong
*
*/
@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("anno")
@Slf4j
public class UserMapperTest {
@Autowired
UserMapper userMpper;
@Test
public void testInsert() {
User user = new User();
user.setCode("002");
user.setName("name002");
user.setStatus(StatusEnum.ENABLE);
//新增
userMpper.insert(user);
}
@Test
public void testQueryOne() {
User user = userMpper.queryOne(1L);
log.info("id為1的查詢結果為:{}", user);
}
@Test
public void testUpdate() {
User user = new User();
user.setCode("002");
user.setName("testUpdate");
user.setStatus(StatusEnum.ENABLE);
userMpper.insert(user);
User userUpd = userMpper.queryOne(user.getId());
userUpd.setName("更新name");
userMpper.update(userUpd);
Assert.assertEquals("更新失敗",userUpd.getName(), userMpper.queryOne(user.getId()).getName());
}
@Test
public void testParamSelect() {
String code = "002";
List<User> list = userMpper.queryByParams(code);
log.info("查詢編碼為002,查詢結果為:{}條,結果集為:{}",list.size(), Arrays.toString(list.toArray()));
}
}
執行測試用例後,就可以看見效果了。
具體控制檯輸出就輸出了,可下載原始碼自行測試下。
xml方式
0.配置xml版的mapper。
/**
* xml對映
* @author oKong
*
*/
public interface UserXmlMapper {
User queryOne(Long id);
int insert(User user);
void update(User user);
void delete(Long id);
List<User> queryByParams(@Param("code")String code);
}
沒啥區別,就是講sql語句放入到了xml中進行編寫而已。
1.編寫mapper.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="cn.lqdev.learning.springboot.chapter35.biz.mapper.UserXmlMapper">
<!-- 配置返回型別 -->
<resultMap type="User" id="userResultMap">
<result column="id" property="id"/>
<result column="code" property="code"/>
<result column="name" property="name"/>
<result column="status" property="status"/>
<result column="gmt_create" property="gmtCreate" jdbcType="DATE"/>
<result column="gmt_modified" property="gmtModified" jdbcType="DATE"/>
</resultMap>
<!-- 通用查詢結果列 -->
<sql id="Base_Column_List">
id, code, name, status, gmt_create, gmt_modified
</sql>
<select id="queryOne" resultMap="userResultMap">
select
<include refid="Base_Column_List"></include>
from user
where id = #{id}
</select>
<!-- 返回主鍵id -->
<insert id="insert" parameterType="User" keyProperty="id" useGeneratedKeys="true">
insert into user(code,name,status) values(#{code},#{name}, #{status})
<!-- insert into user(code,name,status) values(#{code},#{name}, #{status, typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}) -->
</insert>
<update id="update" parameterType="User">
update user set code=#{code}, name = #{name}, status = #{status} where id=#{id}
</update>
<delete id="delete">
delete from user where id=#{id}
</delete>
<select id="queryByParams" resultMap="userResultMap">
select
<include refid="Base_Column_List"></include>
from user
where code = #{code}
</select>
</mapper>
2.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>
<!--全域性配置-->
<settings>
<!-- 這個配置使全域性的對映器啟用或禁用快取 -->
<setting name="cacheEnabled" value="true"/>
<!-- 全域性啟用或禁用延遲載入。當禁用時,所有關聯物件都會即時載入 -->
<setting name="lazyLoadingEnabled" value="false"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="defaultExecutorType" value="REUSE"/>
<setting name="defaultStatementTimeout" value="25000"/>
<setting name="aggressiveLazyLoading" value="true"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<typeHandlers>
<!-- 列舉類 -->
<typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"
javaType="cn.lqdev.learning.springboot.chapter35.biz.entity.StatusEnum"/>
</typeHandlers>
</configuration>
對於特殊的型別,可以通過typeHandlers
進行配置。稍後章節也會講解想通過其他的方式進行配置。
3.建立xml方式配置檔案:application-xml.properties
,配置xml和config的路徑地址
# 配置mapper.xml和mybatis-config.xml路徑
mybatis.config-location=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
4.編寫測試類:UserXmlMapperTest.java
此類和UserMapperTest
類似的,唯一區別就是制定了執行環境變數為:xml
@ActiveProfiles("xml")
列舉型別處理器配置
在實體物件中我們設定了列舉型別:
StatusEnum
。在mybatis
中對於列舉的預設配置是由EnumTypeHandler
處理類進行處理的,其會預設使用name
進行賦值。同時mybatis
還提供了一個EnumOrdinalTypeHandler
處理類,其是根據列舉的索引值進行賦值的。
註冊型別處理類有很多中方式,但每一種方式最後都是通過TypeHandlerRegistry
類進行處理的,這裡講解下通過多種方式進行配置。
- 配置檔案中新增屬性:
mybatis.type-handlers-package
:配置處理類的路徑。
# 型別處理類
mybatis.type-handlers-package=cn.lqdev.learning.springboot.chapter35.config
處理類示例:CustomEnumOrdinalTypeHandler.java
。這裡直接繼承EnumOrdinalTypeHandler
進行自定義。
/**
*
* @author oKong
*
*/
//列舉索引處理類
@MappedTypes(value = { StatusEnum.class })
public class CustomEnumOrdinalTypeHandler<E extends Enum<E>> extends EnumOrdinalTypeHandler<E>{
public CustomEnumOrdinalTypeHandler(Class<E> type) {
super(type);
}
}
其中,@MapperType
指定了哪些型別指定此處理類的。
- 自定義
ConfigurationCustomizer
類進行配置(推薦)。
/**
*
* <p>函式名稱: ConfigurationCustomizer </p>
* <p>功能說明: 自定義相關注冊器
*
* </p>
*<p>引數說明:</p>
* @return
*
* @date 建立時間:2018年12月2日
* @author 作者:oKong
*/
@Bean
public ConfigurationCustomizer configurationCustomizer() {
ConfigurationCustomizer config = new ConfigurationCustomizer() {
@Override
public void customize(org.apache.ibatis.session.Configuration configuration) {
// TypeAliasRegistry typeAliasRegistry = configuration.getTypeAliasRegistry();
// mapper介面註冊器
// MapperRegistry mapperRegistry = configuration.getMapperRegistry();
// 型別處理器
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
typeHandlerRegistry.register(StatusEnum.class, EnumOrdinalTypeHandler.class);
}
};
return config;
}
- 通過
SqlSessionFactory
來獲取TypeHandlerRegistry
進行配置。
@Autowired
SqlSessionFactory sqlSessionFactory;
@PostConstruct
public void registerTypeHandler() {
TypeHandlerRegistry registry = sqlSessionFactory.getConfiguration().getTypeHandlerRegistry();
registry.register(StatusEnum.class, EnumOrdinalTypeHandler.class);
}
以上三種都可以進行相關型別的處理類配置,建議直接使用第二種。
完整的MybatisConfig
類:
/**
* mybaits配置
* @author oKong
*
*/
@Configuration
@MapperScan("cn.lqdev.learning.springboot.chapter35.biz.mapper")//mapper地址
public class MybatisConfig {
//使用 SqlSessionFactory 類獲取 TypeHandlerRegistry 進行註冊
// @Autowired
// SqlSessionFactory sqlSessionFactory;
//
// @PostConstruct
// public void registerTypeHandler() {
// TypeHandlerRegistry registry = sqlSessionFactory.getConfiguration().getTypeHandlerRegistry();
// registry.register(StatusEnum.class, EnumOrdinalTypeHandler.class);
// }
/**
*
* <p>函式名稱: ConfigurationCustomizer </p>
* <p>功能說明: 自定義相關注冊器
*
* </p>
*<p>引數說明:</p>
* @return
*
* @date 建立時間:2018年12月2日
* @author 作者:oKong
*/
@Bean
public ConfigurationCustomizer configurationCustomizer() {
ConfigurationCustomizer config = new ConfigurationCustomizer() {
@Override
public void customize(org.apache.ibatis.session.Configuration configuration) {
// TypeAliasRegistry typeAliasRegistry = configuration.getTypeAliasRegistry();
// mapper介面註冊器
// MapperRegistry mapperRegistry = configuration.getMapperRegistry();
// 型別處理器
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
typeHandlerRegistry.register(StatusEnum.class, EnumOrdinalTypeHandler.class);
}
};
return config;
}
}
參考資料
總結
本章節主要簡單介紹了
mybatis
整合的兩種模式。兩種模式各有特點,註解版適合簡單快速的模式,而xml方式適合相對複雜的sql語句,寫在xml中,可以進行統一修改,而不需要去修改java程式碼。對於原生使用mybatis
而言,感覺也是比較簡單的,就是寫起語句比較麻煩,都需要手動去編寫。對於程式碼生成器,大家可執行搜尋相關材料下,大致看了下有點麻煩。所以還是選擇一個腳手架吧,mybatis-plus
是一個很好的選擇。當然了其他的腳手架框架了,大家可自行根據實際情況進行抉擇。前幾天去看部落格評論時,有人覺得開發本來就很累了還要學習這種小框架,我覺得吧,這些小框架可以節省多少繁瑣的工作呀。讓開發人員可以專注於業務程式碼,多美好的一件事情呀。將近兩星期沒有寫,可能寫的有些亂了,大家可以直接下載原始碼示例進行檢視下,原本想分開兩個工程進行講解,感覺也沒有必要,就合併在一起了,通過不同的環境配置進行切換,還請諒解呀!
最後
目前網際網路上很多大佬都有
SpringBoot
系列教程,如有雷同,請多多包涵了。原創不易,碼字不易,還希望大家多多支援。若文中有所錯誤之處,還望提出,謝謝。
老生常談
- 個人QQ:
499452441
- 公眾號:
lqdevOps
個人部落格:http://blog.lqdev.cn
完整示例:https://github.com/xie19900123/spring-boot-learning/tree/master/chapter-35
原文地址:http://blog.lqdev.cn/2018/12/03/springboot/chapter-thirty-five/