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@Slf4jpublic 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)
在此我向大家推薦一個架構學習交流圈:830478757 幫助突破瓶頸 提升思維能力
具體的可以去官網查閱: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")@Slf4jpublic 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
進行配置。稍後章節也會講解想通過其他的方式進行配置。
在此我向大家推薦一個架構學習交流圈:830478757 幫助突破瓶頸 提升思維能力
3.創建xml方式配置文件:application-xml.properties
,配置xml和config的路徑地址
# 配置mapper.xml和mybatis-config.xml路徑mybatis.config-location=classpath:mybatis/mybatis-config.xmlmybatis.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
是一個很好的選擇。當然了其他的腳手架框架了,大家可自行根據實際情況進行抉擇。前幾天去看博客評論時,有人覺得開發本來就很累了還要學習這種小框架,我覺得吧,這些小框架可以節省多少繁瑣的工作呀。讓開發人員可以專注於業務代碼,多美好的一件事情呀。大家可以直接下載源碼示例進行查看下,原本想分開兩個工程進行講解,感覺也沒有必要,就合併在一起了,通過不同的環境配置進行切換,還請諒解呀