一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|

服務器之家 - 編程語言 - JAVA教程 - Mybatis返回單個實體或者返回List的實現(xiàn)

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

2020-07-10 19:43柳風123 JAVA教程

這篇文章主要介紹了Mybatis返回單個實體或者返回List的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

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

實體

?
1
2
3
4
5
6
7
8
9
10
package com.test.User
 
public class User{
private String userId;
private String userName;
private String userPassword;
private Date createTime;
...
setter getter....
}

DAO

?
1
2
3
4
5
6
public interface UserMapper{
    User getUserById(String userId); //返回單個實體
    List<User> getUserByName(String userName); //返回List
    Map<String,Object> getUserInfoById(String userId);
    List<Map<String,Object>> getUserInfoByName(String userName);
}

數(shù)據庫

?
1
2
3
4
5
6
7
create table user{
USER_ID varchar(40),
USER_NAME varchar(200),
USER_PASSWORD varchar(100),
CREATE_TIME datetime,
....
}

1.返回某個實體

mybatis映射文件

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

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

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

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

TooManyResultsException

返回單個實體時,調用方法 getUserById,但是如果是因為數(shù)據錯誤導致實際查詢結果存在多個時,則會拋出異常。

?
1
User getUserById(String userId); //返回單個實體

當實際返回值有多個時則拋出異常。

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

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

2.返回List<entityName>

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

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

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

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

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

推薦使用返回List的方式來查詢結果

?
1
2
3
4
5
6
7
//查詢單條結果
List<User> userList= mapper.getUserByName(userName);
if(userList.isEmpty() || userList.size() >1)//期望獲得一條結果
    //業(yè)務處理,一般是拋出異常或者直接返回錯誤結果
    //return xx;   
    //throw xxx
User user = userList.get(0);

擴展

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

這是因為Mybatis 在內部進行數(shù)據查詢的時,無論查詢單條還是多條都是通過selectList實現(xiàn)的,不同的是查詢單條Mybatis會獲取第一條,并且如果結果中存在多條時拋出異常 TooManyResultsException

查詢單數(shù)據

?
1
2
3
4
5
6
7
8
9
10
11
12
@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;
}
}

查詢列表

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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ù)據還是列表呢?

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 對象就是 Mapper中的方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// select 查詢操作
 case SELECT:  
        // 方法中沒有定義返回結果,并且方法存在結果處理器
  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()) {
    // 返回游標
   result = executeForCursor(sqlSession, args);
  } else {
  // 返回單條數(shù)據
   Object param = method.convertArgsToSqlCommandParam(args);
   result = sqlSession.selectOne(command.getName(), param);
  }
  break;

3.返回Map

返回map 本質上也是返回一個實體。

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

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

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

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

Oracle環(huán)境下:

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

最終返回Map:

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

如果使用map接受則不會該map不存在數(shù)據. 因為Mybatis默認情況下,不會進行賦值,此時該key-value缺失
如果需要改變該行為可以在mybatis配置文件中設置

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

callSettersOnNulls指定當返回結果為null 的時候是否調用映射對象的 setter(map 對象時為 put)方法,注意基本類型(int、boolean等)是不能設置成 null 的。

配置之后的返回結果:

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

4.返回List<Map>

?
1
2
3
<select id="" parameterType="" resultType="map">
        sql_caluse
    </select>

resultType設置為map,跟上面一樣resultType設置為List集合中元素的類型。

關于mybatis傳遞多個參數(shù),可以參考mybatis3-傳遞多參數(shù)

注意:

偶然發(fā)現(xiàn)Mybatis 會自動對重名的列做去重。

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

?
1
2
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';

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

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

?
1
2
3
4
5
6
7
[
    {"parent_id":0,"name":"圖書","id":1},
    {"parent_id":0,"name":"圖書","id":1},
    {"parent_id":0,"name":"圖書","id":1},
    {"parent_id":0,"name":"圖書","id":1}
    ......
]

稍微修改一下字段名稱。

?
1
2
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';
?
1
2
3
4
5
6
7
[
    {"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”,可以正常顯示。這是因為使用sql 查詢出的同名的列名自動追加數(shù)字做區(qū)分,而實際保存在 元數(shù)據信息中的列名還是原來的。就如同Excel 的單元格一樣,不管單元格內容以什么樣式顯示都不會修改實際值。

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

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

小結:

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

 

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

 

到此這篇關于Mybatis返回單個實體或者返回List的實現(xiàn)的文章就介紹到這了,更多相關Mybatis返回實體或者返回List內容請搜索服務器之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/yamadeee/article/details/79774638

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 三级aa久久 | 给我视频免费看 | 久久99亚洲AV无码四区碰碰 | 特黄特色大片免费视频播放 | xxxxxx日本处大片免费看 | 亚洲视频一区二区在线观看 | 亚洲精品在线播放 | 拔插拔插8x8x海外华人免费视频 | 欧美日本一道高清二区三区 | 日本人做受全过程视频 | 国产亚洲欧美在线中文bt天堂网 | 日韩欧美亚洲一区二区综合 | 小早川怜子亚洲综合中文字幕 | 91久久色| 黄在线观看www免费看 | 性刺激欧美三级在线现看中文 | 俄罗斯美女大逼 | 久久精品小视频 | 欧美黑人性 | 国产精品国产精品国产三级普 | 亚洲一级特黄特黄的大片 | 好大好硬好长好爽a网站 | 五月激情丁香婷婷综合第九 | 亚洲精品人成网在线播放影院 | 日本精品中文字幕在线播放 | 欧美区视频| 特黄特级高清免费视频毛片 | 动漫白丝袜美女羞羞 | 天海翼黄色三级 | 我半夜摸妺妺的奶C了她 | 无码国产成人777爽死在线观看 | 亚洲精品97福利在线 | 免费国产午夜高清在线视频 | 免费观看美女被cao视频 | 欧美xbxbxbbxxbb精品 | 99热久久这里只有精品23 | 午夜在线观看视频 | 亚洲精品一区二区观看 | caoporn超碰| 忘忧草研究院一二三 | 免费看1级伦理 |