最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Mybatis返回單個(gè)實(shí)體或者返回List的實(shí)現(xiàn)

 更新時(shí)間:2020年07月10日 14:19:18   作者:柳風(fēng)123  
這篇文章主要介紹了Mybatis返回單個(gè)實(shí)體或者返回List的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

Mybatis 的強(qiáng)大之處之一體現(xiàn)在映射語(yǔ)句上,讓我們可以使用簡(jiǎn)單的配置,就可以實(shí)現(xiàn)對(duì)參數(shù)和返回結(jié)果的映射。

實(shí)體

package com.test.User

public class User{
private String userId;
private String userName;
private String userPassword;
private Date createTime;
...
setter getter....
}

DAO

public interface UserMapper{
	User getUserById(String userId); //返回單個(gè)實(shí)體
	List<User> getUserByName(String userName); //返回List
	Map<String,Object> getUserInfoById(String userId);
	List<Map<String,Object>> getUserInfoByName(String userName);
}

數(shù)據(jù)庫(kù)

create table user{
USER_ID varchar(40),
USER_NAME varchar(200),
USER_PASSWORD varchar(100),
CREATE_TIME datetime,
....
}

1.返回某個(gè)實(shí)體

mybatis映射文件

<select id="getUserById" parameterType="string" resultType="com.test.User">
		select * from user where id = #{userId}
	</select>
  • id :identification:語(yǔ)句的標(biāo)識(shí),在同一個(gè)mapper映射文件下id需要唯一
  • parameterType: 參數(shù)類型,可以不寫。因?yàn)?MyBatis 可以推斷出傳入語(yǔ)句的具體參數(shù)
  • resultType: 全限定類名或者是類型別名.

當(dāng)使用resultType來(lái)映射結(jié)果時(shí),需要 數(shù)據(jù)庫(kù)表的列名或列別名 和 類的屬性名相同,這樣才能進(jìn)行字段的匹配(USER_ID 和userId 就不能匹配)。但是如果在Mybatis配置文件中設(shè)置了

<settings>
 <setting name="mapUnderscoreToCamelCase" value="true"/> <!--開啟自動(dòng)駝峰命名規(guī)則(camel case)映射,即從經(jīng)典數(shù)據(jù)庫(kù)列名 A_COLUMN 到經(jīng)典 Java 屬性名 aColumn 的類似映射。-->
</settings>

此時(shí),表列名的下劃線標(biāo)記方式可以映射到駝峰標(biāo)記的形式。(USER_ID -> userId)。mybatis進(jìn)行映射時(shí)會(huì)將實(shí)體類屬性和數(shù)據(jù)庫(kù)列名(別名)都轉(zhuǎn)化為大寫來(lái)比較,所以USER_ID 和 UserId,userID等都可以匹配。

TooManyResultsException

返回單個(gè)實(shí)體時(shí),調(diào)用方法 getUserById,但是如果是因?yàn)閿?shù)據(jù)錯(cuò)誤導(dǎo)致實(shí)際查詢結(jié)果存在多個(gè)時(shí),則會(huì)拋出異常。

User getUserById(String userId); //返回單個(gè)實(shí)體

當(dāng)實(shí)際返回值有多個(gè)時(shí)則拋出異常。

org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 2

除非可以確定最多只能查詢到一條結(jié)果,否則的話不建議這么寫.可以嘗試返回集合的方式。

2.返回List<entityName>

<select id="getUserByName" resultType="com.test.User">
		select * from user where user_name = #{userName}
	</select>

返回List<T> 集合時(shí),resultType設(shè)置為集合元素的類型即T。然后使用返回幾何數(shù)據(jù)的Mapper方法即可。

List<User> getUserByName(String userName); //返回List

從上面可以看到,返回單個(gè)實(shí)體與返回集合的resultType指定類型是一樣的,不一樣的地方在Mapper接口或者sqlSession中定義的返回結(jié)果類型。實(shí)際上mybatis執(zhí)行查詢的時(shí)候也都是使用sqlSession.selectList()來(lái)進(jìn)行查詢的。

  • 使用Mapper 接口的方式的查詢結(jié)果時(shí),Mybatis會(huì)生成該接口的代理類(MapperProxy),然后根據(jù)Method的getReturnType()方法,拿到返回類型,來(lái)確定返回的是列表還是單個(gè)實(shí)體。最后也是調(diào)用sqlSession的一些方法。
  • 使用SqlSession時(shí),提供了selectOne() 或者selectList()來(lái)返回單個(gè)實(shí)體或者集合。selectOne 實(shí)際會(huì)調(diào)用selectList獲取結(jié)果。

推薦使用返回List的方式來(lái)查詢結(jié)果

//查詢單條結(jié)果
List<User> userList= mapper.getUserByName(userName);
if(userList.isEmpty() || userList.size() >1)//期望獲得一條結(jié)果
	//業(yè)務(wù)處理,一般是拋出異?;蛘咧苯臃祷劐e(cuò)誤結(jié)果
	//return xx;	
	//throw xxx
User user = userList.get(0);

擴(kuò)展

為什么查詢單條和查詢多條使用的是相同的resultType,而返回的結(jié)果不同呢。

這是因?yàn)镸ybatis 在內(nèi)部進(jìn)行數(shù)據(jù)查詢的時(shí),無(wú)論查詢單條還是多條都是通過(guò)selectList實(shí)現(xiàn)的,不同的是查詢單條Mybatis會(huì)獲取第一條,并且如果結(jié)果中存在多條時(shí)拋出異常 TooManyResultsException。

查詢單數(shù)據(jù)

 @Override
 public <T> T selectOne(String statement, Object parameter) {
 // Popular vote was to return null on 0 results and throw exception on too many.
 List<T> list = this.<T>selectList(statement, parameter);
 if (list.size() == 1) {
  return list.get(0);
 } else if (list.size() > 1) {
  throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
 } else {
  return null;
 }
 }

查詢列表

 private <E> Object executeForMany(SqlSession sqlSession, Object[] args) {
 List<E> result;
 Object param = method.convertArgsToSqlCommandParam(args);
 if (method.hasRowBounds()) {
  RowBounds rowBounds = method.extractRowBounds(args);
  result = sqlSession.<E>selectList(command.getName(), param, rowBounds);
 } else {
  result = sqlSession.<E>selectList(command.getName(), param);
 }
 // issue #510 Collections & arrays support
 if (!method.getReturnType().isAssignableFrom(result.getClass())) {
  if (method.getReturnType().isArray()) {
  return convertToArray(result);
  } else {
  return convertToDeclaredCollection(sqlSession.getConfiguration(), result);
  }
 }
 return result;
 }

那么Mybatis怎么知道是查詢的單條數(shù)據(jù)還是列表呢?

  • 如果直接使用 SqlSession,這個(gè)需要自己控制 是調(diào)用selectOne 還是 selectList
  • 如果使用 Mapper 接口,Mybatis會(huì)解析Mapper接口中的方法,會(huì)根據(jù)方法的返回值,判斷該方法屬于那種類型

解析方法中的參數(shù)、返回值

public MethodSignature(Configuration configuration, Class<?> mapperInterface, Method method) {
  Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);
  if (resolvedReturnType instanceof Class<?>) {
  this.returnType = (Class<?>) resolvedReturnType;
  } else if (resolvedReturnType instanceof ParameterizedType) {
  this.returnType = (Class<?>) ((ParameterizedType) resolvedReturnType).getRawType();
  } else {
  this.returnType = method.getReturnType();
  }
  this.returnsVoid = void.class.equals(this.returnType);
  this.returnsMany = (configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray());
  this.returnsCursor = Cursor.class.equals(this.returnType);
  this.mapKey = getMapKey(method);
  this.returnsMap = (this.mapKey != null);
  this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
  this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
  this.paramNameResolver = new ParamNameResolver(configuration, method);
 }

method 對(duì)象就是 Mapper中的方法

// select 查詢操作
 case SELECT:	
 		// 方法中沒有定義返回結(jié)果,并且方法存在結(jié)果處理器
  if (method.returnsVoid() && method.hasResultHandler()) {
   executeWithResultHandler(sqlSession, args);
   result = null;
  } else if (method.returnsMany()) {
  // 返回列表
   result = executeForMany(sqlSession, args);
  } else if (method.returnsMap()) {
  // 返回Map
   result = executeForMap(sqlSession, args);
  } else if (method.returnsCursor()) {
  	// 返回游標(biāo)
   result = executeForCursor(sqlSession, args);
  } else {
  // 返回單條數(shù)據(jù)
   Object param = method.convertArgsToSqlCommandParam(args);
   result = sqlSession.selectOne(command.getName(), param);
  }
  break;

3.返回Map

返回map 本質(zhì)上也是返回一個(gè)實(shí)體。

<select id="getUserInfoById" resultType="map">
		select * from user where id=#{userId}
	</select>

如果想要返回單個(gè)Map<key,value>集合,只需要設(shè)置resultType="map"就可以了,此時(shí)返回的實(shí)例類型是HashMap。
Map的key就是數(shù)據(jù)表的列名或者列別名, value 就是查詢的數(shù)據(jù)庫(kù)中的結(jié)果。如果需要返回LinkedHashMap,需要使用全限定類名resultType="java.util.LinkedHashMap"

注意: 返回列對(duì)應(yīng)的結(jié)果為 null,則不顯示該 key - value 鍵值對(duì)(只針對(duì)該行數(shù)據(jù)對(duì)應(yīng)的Map)

<select id="getUserInfoById" resultType="map">
		select * from user where id=#{userId}
	</select>

Oracle環(huán)境下:


最終返回Map:

{"name ":"全部"}
// code 不是顯示

如果使用map接受則不會(huì)該map不存在數(shù)據(jù). 因?yàn)镸ybatis默認(rèn)情況下,不會(huì)進(jìn)行賦值,此時(shí)該key-value缺失
如果需要改變?cè)撔袨榭梢栽趍ybatis配置文件中設(shè)置

<setting name="callSettersOnNulls" value="true"/>

callSettersOnNulls指定當(dāng)返回結(jié)果為null 的時(shí)候是否調(diào)用映射對(duì)象的 setter(map 對(duì)象時(shí)為 put)方法,注意基本類型(int、boolean等)是不能設(shè)置成 null 的。

配置之后的返回結(jié)果:

{"code":null,"name":"全部"}

4.返回List<Map>

<select id="" parameterType="" resultType="map">
		sql_caluse
	</select>

resultType設(shè)置為map,跟上面一樣resultType設(shè)置為L(zhǎng)ist集合中元素的類型。

關(guān)于mybatis傳遞多個(gè)參數(shù),可以參考mybatis3-傳遞多參數(shù)

注意:

偶然發(fā)現(xiàn)Mybatis 會(huì)自動(dòng)對(duì)重名的列做去重。

比如我有一組數(shù)據(jù),使用Map接受

SELECT l1.*,l2.*,l3.* FROM ITEM_CAT l1 LEFT JOIN ITEM_CAT l2 ON l1.Id=L2.PARENT_ID LEFT JOIN ITEM_CAT l3
  ON l2.Id=L3.PARENT_ID WHERE L1.PARENT_ID='0';

實(shí)際返回結(jié)果,會(huì)發(fā)現(xiàn) name1,name2 都沒有映射到Map中

[
	{"parent_id":0,"name":"圖書","id":1},
	{"parent_id":0,"name":"圖書","id":1},
	{"parent_id":0,"name":"圖書","id":1},
	{"parent_id":0,"name":"圖書","id":1}
	......
]

稍微修改一下字段名稱。

 SELECT l1.*,l2.*,l3.*,'test' as name1 FROM ITEM_CAT l1 LEFT JOIN ITEM_CAT l2 ON l1.Id=L2.PARENT_ID LEFT JOIN ITEM_CAT l3
  ON l2.Id=L3.PARENT_ID WHERE L1.PARENT_ID='0';
[
	{"parent_id":0,"name":"圖書","id":1,"name1":"test"},
	{"parent_id":0,"name":"圖書","id":1,"name1":"test"},
	{"parent_id":0,"name":"圖書","id":1,"name1":"test"},
	{"parent_id":0,"name":"圖書","id":1,"name1":"test"}
	......
]

可以看到 新增的自定義列名 “name1”,可以正常顯示。這是因?yàn)槭褂胹ql 查詢出的同名的列名自動(dòng)追加數(shù)字做區(qū)分,而實(shí)際保存在 元數(shù)據(jù)信息中的列名還是原來(lái)的。就如同Excel 的單元格一樣,不管單元格內(nèi)容以什么樣式顯示都不會(huì)修改實(shí)際值。

小結(jié):

  • 返回集合與返回單個(gè)實(shí)體對(duì)象在映射文件的寫法是一致的,不同的地方在于Mapper的返回類型不同。
  • 如果不確定返回值是否是唯一的,盡量使用 集合的返回方式。然乎使用get(0)的方式獲取實(shí)體。
  • 如果返回實(shí)體,一般情況會(huì)使用 resultMap來(lái)映射返回結(jié)果。這樣更清晰,直觀,而且還可以使用typeHandler對(duì)數(shù)據(jù)類型做進(jìn)一步處理

返回結(jié)果 Mapper xml
實(shí)體 T getT() returnType=“T”
集合 List<T> getTList() returnType=“T”

到此這篇關(guān)于Mybatis返回單個(gè)實(shí)體或者返回List的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Mybatis返回實(shí)體或者返回List內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring實(shí)戰(zhàn)之使用ClassPathResource加載xml資源示例

    Spring實(shí)戰(zhàn)之使用ClassPathResource加載xml資源示例

    這篇文章主要介紹了Spring實(shí)戰(zhàn)之使用ClassPathResource加載xml資源,結(jié)合實(shí)例形式分析了Spring使用ClassPathResource加載xml資源的具體實(shí)現(xiàn)步驟與相關(guān)操作技巧,需要的朋友可以參考下
    2019-12-12
  • SpringBoot 下集成緩存工具類 CacheManager

    SpringBoot 下集成緩存工具類 CacheManager

    這篇文章主要介紹了Springboot下集成緩存工具類CacheManager,想進(jìn)一步了解相關(guān)知識(shí)的同學(xué),可以詳細(xì)閱讀本文
    2023-03-03
  • Java實(shí)現(xiàn)字符串倒序輸出的四種方法匯總

    Java實(shí)現(xiàn)字符串倒序輸出的四種方法匯總

    這篇文章主要介紹了Java實(shí)現(xiàn)字符串倒序輸出的四種方法匯總,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Struts和servlet不能共存問(wèn)題解決方法

    Struts和servlet不能共存問(wèn)題解決方法

    這篇文章主要介紹了Struts和servlet不能共存問(wèn)題解決方法,共有三種方法,需要的朋友可以參考下。
    2017-09-09
  • java:程序包org.springframework.boot不存在的完美解決方法

    java:程序包org.springframework.boot不存在的完美解決方法

    最近項(xiàng)目中運(yùn)行的時(shí)候提示了"java: 程序包org.springframework.boot不存在",下面這篇文章主要給大家介紹了關(guān)于java:程序包org.springframework.boot不存在的完美解決方法,需要的朋友可以參考下
    2023-05-05
  • Spring MVC Mybatis多數(shù)據(jù)源的使用實(shí)例解析

    Spring MVC Mybatis多數(shù)據(jù)源的使用實(shí)例解析

    項(xiàng)目需要從其他網(wǎng)站獲取數(shù)據(jù),因?yàn)槭桥R時(shí)加的需求,這篇文章主要介紹了Spring MVC Mybatis多數(shù)據(jù)源的使用實(shí)例解析,需要的朋友可以參考下
    2016-12-12
  • java實(shí)現(xiàn)md5加密示例

    java實(shí)現(xiàn)md5加密示例

    這篇文章主要介紹了java實(shí)現(xiàn)md5加密示例,需要的朋友可以參考下
    2014-05-05
  • idea常用的18個(gè)設(shè)置(程序員必不可少)

    idea常用的18個(gè)設(shè)置(程序員必不可少)

    這篇文章主要給大家介紹了關(guān)于idea常用的18個(gè)設(shè)置,這些對(duì)程序員們來(lái)說(shuō)必不可少,idea開發(fā)常用基本且非常實(shí)用的配置,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-08-08
  • Java使用反射生成JDK代理示例

    Java使用反射生成JDK代理示例

    這篇文章主要介紹了Java使用反射生成JDK代理,結(jié)合實(shí)例形式分析了java基于反射實(shí)現(xiàn)jdk動(dòng)態(tài)代理相關(guān)操作技巧,需要的朋友可以參考下
    2019-07-07
  • Rocketmq事務(wù)消息之半消息詳解

    Rocketmq事務(wù)消息之半消息詳解

    這篇文章主要介紹了Rocketmq事務(wù)消息之半消息詳解,RocketMQ的事務(wù)消息支持在業(yè)務(wù)邏輯與發(fā)送消息之間提供事務(wù)保證,RocketMQ通過(guò)兩階段的方式提供事務(wù)消息的支持,需要的朋友可以參考下
    2023-09-09

最新評(píng)論

古田县| 三门峡市| 汽车| 即墨市| 陕西省| 罗山县| 昌黎县| 翁牛特旗| 宝坻区| 环江| 汤阴县| 竹山县| 浦北县| 靖边县| 类乌齐县| 梁河县| 定安县| 安康市| 大埔县| 崇左市| 西宁市| 吐鲁番市| 承德县| 绵阳市| 扎鲁特旗| 白水县| 广汉市| 牙克石市| 区。| 当雄县| 偏关县| 富顺县| 朝阳区| 岳阳市| 临邑县| 锦州市| 张北县| 开封县| 乌海市| 湘潭市| 河津市|