問題描述
在使用mybaits-plus的時候定義的Mapper接口實現了BaseMapper,沒有編寫Mapper對應的xml,大部分查詢使用框架的接口進行查詢基本屬性返回都是正常,復雜對象在sql中會進行查詢,但是返回對象中卻未包含相關屬性。
問題原因
沒有開啟自動映射
實體類在使用@TableName
注解修飾時,在具有復雜對象的實體中沒有開啟autoResultMap
屬性映射,這樣在本身沒有編寫Mapper.xml的情況下會導致框架只會生成基礎屬性的映射,復雜對象不會處理,即使在復雜字段上標注了typeHandler = JacksonTypeHandler.class
也無濟于事。
使用@Select
注解自定義SQL
實體類開啟了autoResultMap
屬性映射,但是在Mapper接口中使用@Select
注解編寫來進行查詢。使用框架提供的查詢方法復雜屬性能正常返回,但是使用自定義查詢復雜屬性返回為空。
解決方案
未開啟自動映射-開啟自動映射
因為autoResultMap
默認是false的,如果實體對象中沒有復雜屬性,則不開也無所謂,mybatis-plus框架會將基礎屬性自動進行映射;但是如果實體使用了json,list等復雜屬性,則需要顯示開啟自動映射,并且在@TableField
中表明使用的handler
類型,這樣框架才會在查詢出值之后知道怎么利用哪個handler
來進行值的轉換。
解決效果
庫中的值
未開啟自動映射查詢結果
涉及的類
@TableName(value = "user_table")
@Data
public class UserEntity { private String name; private Integer age; @TableField(value = "table_desc",typeHandler = JacksonTypeHandler.class,jdbcType = JdbcType.OTHER) private List<String> tableDesc; }@Mapper
public interface UserEntityMapper extends BaseMapper<UserEntity> {
}//使用框架的查詢
@RestController
@RequestMapping("/test")
public class TestController { @Resource UserEntityMapper userEntityMapper; @GetMapping("/query") public String getQuery(){ return JSONObject.toJSONString(userEntityMapper.selectList(null)); } }
查詢結果
[ { "age": 4, "name": "123" }, { "age": 1, "name": "33333" }
]
開啟自動映射
涉及的類
@TableName(value = "user_table",autoResultMap = true)
@Data
public class UserEntity { private String name; private Integer age; @TableField(value = "table_desc",typeHandler = JacksonTypeHandler.class,jdbcType = JdbcType.OTHER) private List<String> tableDesc; }
查詢結果
[ { "age": 4, "name": "123", "tableDesc": [ "age", "123" ] }, { "age": 1, "name": "33333", "tableDesc": [ "1123", "2131" ] }
]
使用@Select
自定義SQL-使用@ResultMap
指定映射
使用@ResultMap
的前提是開啟了自動映射,這樣框架生成的ResultMap
對象中會包含我們指定對象的handler
類,然后在@Select
方法上添加@ResultMap
注解,這樣框架在執行自定義的SQL語句時就會知道使用哪個對象來進行數據轉換。
@ResultMap
注解中的值命名方式是 #{Mapper對象全路徑}.mybatis-plus_#{實體類名}
未添加@ResultMap
注解查詢
涉及的類
@TableName(value = "user_table")
@Data
public class UserEntity { private String name; private Integer age; @TableField(value = "table_desc",typeHandler = JacksonTypeHandler.class,jdbcType = JdbcType.OTHER) private List<String> tableDesc; }@Mapper
public interface UserEntityMapper extends BaseMapper<UserEntity> { @Select("select * from user_table ")List<UserEntity> getAllValue(); }@RestController
@RequestMapping("/test")
public class TestController { @Resource UserEntityMapper userEntityMapper; @GetMapping("/query") public String getQuery(){ return JSONObject.toJSONString(userEntityMapper.getAllValue()); } }
查詢結果
[ { "age": 4, "name": "123" }, { "age": 1, "name": "33333" }
]
添加@ResultMap
注解
涉及的類
@Mapper
public interface UserEntityMapper extends BaseMapper<UserEntity> { @Select("select * from user_table ")//命名方式是 ${Mapper對象全路徑}.mybatis-plus_${實體類名}@ResultMap("com.example.UserEntityMapper.mybatis-plus_UserEntity")List<UserEntity> getAllValue(); }
查詢結果
[ { "age": 4, "name": "123", "tableDesc": [ "age", "123" ] }, { "age": 1, "name": "33333", "tableDesc": [ "1123", "2131" ] }
]
原理分析
1、執行SQL
org.apache.ibatis.executor.statement.PreparedStatementHandler#query
方法中會執行SQL,獲取查出的值
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#applyAutomaticMappings
方法中主要是對屬性進行轉換,此時autoMapping
只有兩個基礎字段的映射,并沒有table_desc
字段的映射
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#createAutomaticMappings
方法中會構造/獲取當前方法相關的字段映射,key是方法方法全路徑
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#getRowValue
方法中可以看到mybatis的configuration
中resultMaps
對象中有4個鍵值對,其中
- 以方法名命名的是是沒有屬性映射的,所以在執行時復雜屬性獲取不到映射就不會進行賦值
- 以實體結尾的映射是由屬性映射的,所以我們指定該值為
@ResultMap
內容就能對復雜對象進行賦值