MybatisPlus字段類型轉(zhuǎn)換的實現(xiàn)示例
先來回憶下在mybatis中的resultMap作用和是什么
resultMap的作用是什么
在使用傳統(tǒng)的mybatis時,我們一般都會在xml文件定義一個ResultMap
對每個字段都有自己的定義都有兩個類型
javaType可以不顯式寫出來,mybatis可以根據(jù)指定的實體類推斷出來
jdbcType 也就是對應到數(shù)據(jù)庫中的字段類型
mybatis完成數(shù)據(jù)庫的數(shù)據(jù)到java實體類型的轉(zhuǎn)換這兩個類型是必不可少的。會根據(jù)javaType和jdbcType去匹配到對應的處理器完成類型轉(zhuǎn)換
mybatis內(nèi)置了很多typeHandler在啟動時注冊
public TypeHandlerRegistry(Configuration configuration) { this.unknownTypeHandler = new UnknownTypeHandler(configuration); register(Boolean.class, new BooleanTypeHandler()); register(boolean.class, new BooleanTypeHandler()); register(JdbcType.BOOLEAN, new BooleanTypeHandler()); register(JdbcType.BIT, new BooleanTypeHandler()); register(Byte.class, new ByteTypeHandler()); register(byte.class, new ByteTypeHandler()); register(JdbcType.TINYINT, new ByteTypeHandler()); register(Short.class, new ShortTypeHandler()); register(short.class, new ShortTypeHandler()); register(JdbcType.SMALLINT, new ShortTypeHandler()); register(Integer.class, new IntegerTypeHandler()); register(int.class, new IntegerTypeHandler()); register(JdbcType.INTEGER, new IntegerTypeHandler()); register(Long.class, new LongTypeHandler()); register(long.class, new LongTypeHandler()); register(Float.class, new FloatTypeHandler()); register(float.class, new FloatTypeHandler()); register(JdbcType.FLOAT, new FloatTypeHandler()); register(Double.class, new DoubleTypeHandler()); register(double.class, new DoubleTypeHandler()); register(JdbcType.DOUBLE, new DoubleTypeHandler()); register(Reader.class, new ClobReaderTypeHandler()); register(String.class, new StringTypeHandler()); register(String.class, JdbcType.CHAR, new StringTypeHandler()); register(String.class, JdbcType.CLOB, new ClobTypeHandler()); register(String.class, JdbcType.VARCHAR, new StringTypeHandler()); register(String.class, JdbcType.LONGVARCHAR, new StringTypeHandler()); register(String.class, JdbcType.NVARCHAR, new NStringTypeHandler()); register(String.class, JdbcType.NCHAR, new NStringTypeHandler()); register(String.class, JdbcType.NCLOB, new NClobTypeHandler()); register(JdbcType.CHAR, new StringTypeHandler()); register(JdbcType.VARCHAR, new StringTypeHandler()); register(JdbcType.CLOB, new ClobTypeHandler()); register(JdbcType.LONGVARCHAR, new StringTypeHandler()); register(JdbcType.NVARCHAR, new NStringTypeHandler()); register(JdbcType.NCHAR, new NStringTypeHandler()); register(JdbcType.NCLOB, new NClobTypeHandler()); register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler()); register(JdbcType.ARRAY, new ArrayTypeHandler()); register(BigInteger.class, new BigIntegerTypeHandler()); register(JdbcType.BIGINT, new LongTypeHandler()); register(BigDecimal.class, new BigDecimalTypeHandler()); register(JdbcType.REAL, new BigDecimalTypeHandler()); register(JdbcType.DECIMAL, new BigDecimalTypeHandler()); register(JdbcType.NUMERIC, new BigDecimalTypeHandler()); register(InputStream.class, new BlobInputStreamTypeHandler()); register(Byte[].class, new ByteObjectArrayTypeHandler()); register(Byte[].class, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler()); register(Byte[].class, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler()); register(byte[].class, new ByteArrayTypeHandler()); register(byte[].class, JdbcType.BLOB, new BlobTypeHandler()); register(byte[].class, JdbcType.LONGVARBINARY, new BlobTypeHandler()); register(JdbcType.LONGVARBINARY, new BlobTypeHandler()); register(JdbcType.BLOB, new BlobTypeHandler()); register(Object.class, unknownTypeHandler); register(Object.class, JdbcType.OTHER, unknownTypeHandler); register(JdbcType.OTHER, unknownTypeHandler); register(Date.class, new DateTypeHandler()); register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler()); register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler()); register(JdbcType.TIMESTAMP, new DateTypeHandler()); register(JdbcType.DATE, new DateOnlyTypeHandler()); register(JdbcType.TIME, new TimeOnlyTypeHandler()); register(java.sql.Date.class, new SqlDateTypeHandler()); register(java.sql.Time.class, new SqlTimeTypeHandler()); register(java.sql.Timestamp.class, new SqlTimestampTypeHandler()); register(String.class, JdbcType.SQLXML, new SqlxmlTypeHandler()); register(Instant.class, new InstantTypeHandler()); register(LocalDateTime.class, new LocalDateTimeTypeHandler()); register(LocalDate.class, new LocalDateTypeHandler()); register(LocalTime.class, new LocalTimeTypeHandler()); register(OffsetDateTime.class, new OffsetDateTimeTypeHandler()); register(OffsetTime.class, new OffsetTimeTypeHandler()); register(ZonedDateTime.class, new ZonedDateTimeTypeHandler()); register(Month.class, new MonthTypeHandler()); register(Year.class, new YearTypeHandler()); register(YearMonth.class, new YearMonthTypeHandler()); register(JapaneseDate.class, new JapaneseDateTypeHandler()); // issue #273 register(Character.class, new CharacterTypeHandler()); register(char.class, new CharacterTypeHandler()); }
當然我們不指定類型的話mybatis也具備自動推斷類型的能力。
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#createAutomaticMappings
創(chuàng)建自動的字段映射根據(jù)數(shù)據(jù)庫查詢結(jié)果類型,和我們指定的對象字段類型做映射
mybatisPlus如何完成字段映射
當然也可以指定resultMap
@TableNam中有resultMap屬性
/** * 實體映射結(jié)果集, * 只生效與 mp 自動注入的 method */ String resultMap() default "";
@Mapper public interface UserDoMapper extends BaseMapper<User> { @Results( id = "userResultMap", value = {@Result(column = "id",property = "id",javaType = Integer.class,jdbcType = JdbcType.INTEGER), @Result(column = "user_name",property = "userName",javaType = String.class,jdbcType = JdbcType.VARCHAR), @Result(column = "pass_word",property = "passWord",javaType = String.class,jdbcType = JdbcType.VARCHAR), @Result(column = "real_name",property = "realName",javaType = String.class,jdbcType = JdbcType.VARCHAR), @Result(column = "json_arr",property = "jsonArr",typeHandler = StringToJsonArrayBaseTypeHandler.class), } ) @Select("SELECT * FROM user ${ew.customSqlSegment}") User searchDetail( @Param(Constants.WRAPPER) Wrapper<User> wrapper); }
@TableName(resultMap = "userResultMap") public class User { @TableField(jdbcType = JdbcType.INTEGER) private Integer id; @TableField(jdbcType = JdbcType.VARCHAR) private String userName; @TableField(jdbcType = JdbcType.VARCHAR) private String passWord; @TableField(jdbcType = JdbcType.VARCHAR) private String realName; @TableField(typeHandler = StringToJsonArrayBaseTypeHandler.class) private List<String> jsonArr; }
那么我們不想手動定義ResutMap但是又想處理一些復雜類型的轉(zhuǎn)換 就可以使用autoResultMap
自動映射
我們在使用mybatisPlus時在大多數(shù)情況是不會定義resultMap的,那么mybatisPlus是如何完成字段映射的,那么答案顯而易見,就是使用myabtis的字段自動創(chuàng)建映射的功能。
自動映射的方案有什么缺點?
1.對于復雜的類型,無法指定轉(zhuǎn)換方案,無法使用自定義的類型轉(zhuǎn)換器。
2.無法使用關聯(lián)查詢
開啟autoResultMap
@TableName(autoResultMap = true)
那么mybatisPlus會根據(jù)我們的實體類的類型,為我們自動注入resultMap,注入的resultMap也會自動推斷出需要使用的類型轉(zhuǎn)換器當然我們也可以指定
例如
@TableField(typeHandler = StringToJsonArrayBaseTypeHandler.class) private List<String> jsonArr;
也因此說,對于查詢來說,mybatisPlus通過@TableField指定類型轉(zhuǎn)換器,一定要開啟autoResultMap才能生效了。另外mybatisPlus只會為BaseMapper中的方法生成resultMap,而我們自定義的方法,是不會生成的。
例如
@Mapper public interface UserDoMapper extends BaseMapper<User> { @Select("SELECT * FROM user ${ew.customSqlSegment}") User searchDetail( @Param(Constants.WRAPPER) Wrapper<User> wrapper); }
這種寫法autoResultMap和指定的類型轉(zhuǎn)換器是不會生效的。如果有復雜字段轉(zhuǎn)換需求,需要通過@Results標簽定義resultMap
例如
以及通過@ResultMap標簽進行引用
@TableField是能夠指定jdbcType的
不指定jdbcType時mybatis往往也能夠完成自動轉(zhuǎn)換,例如java中的String自然對應到數(shù)據(jù)庫的VAERCHAR
在mybatis無法根據(jù)自動完成javaType到jdbcType的轉(zhuǎn)換時,可以使用@TableField注解完成轉(zhuǎn)換,例如我們想將一個數(shù)據(jù)庫中的VARCHAR類型映射成為java中的Integer,對于插入操作時又要完成Integer到VARCHAR的轉(zhuǎn)換,如果不指定jdbcType那么插入操作將會報錯
@TableField(jdbcType = JdbcType.VARCHAR) private Integer age;
mybatis如何完成查詢參數(shù)轉(zhuǎn)換
前面看的是對于查詢結(jié)果的轉(zhuǎn)換,那么對于插入,更新,查詢等操作,也有一個javaType到jdbcType的轉(zhuǎn)換,對于復雜的字段類型 例如集合轉(zhuǎn)json又是如何生效的?
還是先看傳統(tǒng)mybatis定義映射的寫法
<insert id="insert" parameterType="com.imtech.yasha.sp.common.mapper.dto.sp.ZbLabourBidAuctionList" > insert into zb_labour_bid_auction_list (id, uuid, uuid_t, creater, create_time, updater, update_time, item_d, item_n, order_no, list_no, sub_project_name, construction_tech, unit, project_quantity, unit_price, total, remark, supplier_no, supplier_name) values (#{id,jdbcType=BIGINT}, #{uuid,jdbcType=VARCHAR}, #{uuidT,jdbcType=VARCHAR}, #{creater,jdbcType=VARCHAR}, #{createTime,jdbcType=TIMESTAMP}, #{updater,jdbcType=VARCHAR}, #{updateTime,jdbcType=TIMESTAMP}, #{itemD,jdbcType=VARCHAR}, #{itemN,jdbcType=VARCHAR}, #{orderNo,jdbcType=VARCHAR}, #{listNo,jdbcType=VARCHAR}, #{subProjectName,jdbcType=VARCHAR}, #{constructionTech,jdbcType=VARCHAR}, #{unit,jdbcType=VARCHAR}, #{projectQuantity,jdbcType=NUMERIC}, #{unitPrice,jdbcType=NUMERIC}, #{total,jdbcType=NUMERIC}, #{remark,jdbcType=VARCHAR}, #{supplierNo,jdbcType=VARCHAR}, #{supplierName,jdbcType=VARCHAR}) </insert>
在參數(shù)上一般都會定義jdbcType,至于JavaType可以從parameterType指定的class中推斷出來,這樣javaTyp和jdbcType都被確定下來,很容易匹配到對應的處理器進行類型轉(zhuǎn)換。
那么在mybatisPlus中顯然不會為每個入?yún)⒆侄味xjdbcType,那么對于入?yún)⑹侨绾芜M行轉(zhuǎn)換的,復雜類型又是如何指定的
@TableField(typeHandler = StringToJsonArrayBaseTypeHandler.class) private List<String> jsonArr;
答案也是通過@TableField指定的,而且即使關閉autoResultMap,對于查詢參數(shù)的轉(zhuǎn)換,指定的類型轉(zhuǎn)換器和jdbcType也是會生效的。
到此這篇關于MybatisPlus字段類型轉(zhuǎn)換的實現(xiàn)示例的文章就介紹到這了,更多相關MybatisPlus 字段類型轉(zhuǎn)換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
reactor-logback的AsyncAppender執(zhí)行流程源碼解讀
這篇文章主要為大家介紹了reactor-logback的AsyncAppender執(zhí)行流程源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12使用springmvc的controller層獲取到請求的數(shù)據(jù)方式
這篇文章主要介紹了使用springmvc的controller層獲取到請求的數(shù)據(jù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08Spring AOP之@Around,@AfterReturning使用、切不進去的解決方案
這篇文章主要介紹了Spring AOP之@Around,@AfterReturning使用、切不進去的解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-05SpringSecurity自定義AuthenticationProvider無法@Autowire的解決
這篇文章主要介紹了SpringSecurity自定義AuthenticationProvider無法@Autowire的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12關于springboot配置druid數(shù)據(jù)源不生效問題(踩坑記)
今天日常跟著網(wǎng)課學習,學到了整合druid數(shù)據(jù)源,遇到了好幾個坑,希望這篇文章可以幫助一些和我一樣踩坑的人2021-09-09