前言
最近收到公眾號留言說,單純的
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/