mybatis映射器配置小結(jié)
前面三篇博客我們已經(jīng)多次涉及到映射器的使用了,增刪查基本上都用過(guò)一遍了,但是之前我們只是介紹了基本用法,實(shí)際上mybatis中映射器可以配置的地方還是非常多,今天我們就先來(lái)看看映射器還有哪些需要配置的地方,用好這些配置,可以讓我們的mybatis變得非常靈活。
映射器中的元素還是非常多的,比如select、insert、update、delete、parameterMap、sql、resultMap、cache、cache-ref等,本文我們先來(lái)說(shuō)其中比較重要,也是非常常用的幾個(gè)元素。
select中字段的映射問(wèn)題
select元素用來(lái)執(zhí)行一條查詢語(yǔ)句,Select可以算作是最常用,最復(fù)雜的元素之一,我們?cè)谑褂肧elect的時(shí)候可以自定義元素自定義結(jié)果集等,非常靈活,OK,在說(shuō)Select強(qiáng)大的一面之前,我們先來(lái)看看我們?cè)谇懊鎺灼┛椭惺窃趺词褂肧elect的:
<select id="getUser" resultType="user" parameterType="Long">
select * from user where id = #{id}
</select>我們直接從user表中查詢一條數(shù)據(jù)出來(lái),查詢的結(jié)果是一個(gè)user對(duì)象,即mybatis會(huì)自動(dòng)幫我們把查詢的結(jié)果轉(zhuǎn)為一個(gè)user對(duì)象,那么mybatis在轉(zhuǎn)化的過(guò)程中怎么知道數(shù)據(jù)庫(kù)的哪個(gè)字段對(duì)應(yīng)JavaBean中的哪個(gè)屬性呢?很簡(jiǎn)單,只要兩者的名稱一樣,系統(tǒng)就能就能自動(dòng)識(shí)別出來(lái),我們?cè)谇懊娌┛椭性跀?shù)據(jù)庫(kù)中創(chuàng)建的user表的字段分別為id,username,password,address這四個(gè),實(shí)體類的屬性也是這四個(gè)一模一樣,所以系統(tǒng)會(huì)自動(dòng)將查詢結(jié)果給我們轉(zhuǎn)為User對(duì)象,那么在實(shí)際開(kāi)發(fā)中,JavaBean中的屬性命名我們習(xí)慣于駝峰命名法,在數(shù)據(jù)庫(kù)中我們更常用下劃線命名法,比如我現(xiàn)在創(chuàng)建一個(gè)新的實(shí)體類User:
public class User {
private Long id;
private String userName;
private String password;
private String address;
//省略getter/setter
}然后創(chuàng)建一個(gè)user表,如下:

小伙伴們注意這個(gè)表中有一個(gè)字段和實(shí)體類的屬性名稱不一樣,就是數(shù)據(jù)庫(kù)的user_name字段對(duì)應(yīng)了實(shí)體類的userName屬性,這樣的話,在Select查詢結(jié)果中,mybatis就沒(méi)法幫我們自動(dòng)將查詢結(jié)果轉(zhuǎn)為user對(duì)象了。對(duì)于這種非常常見(jiàn)的需求,我們有三種不同的解決方案,分別如下:
使用SQL語(yǔ)句中的別名功能
我們可以在查詢的時(shí)候自動(dòng)將相關(guān)的列名進(jìn)行修改,如下:
<select id="getUser" resultType="u" parameterType="Long">
select id,user_name as userName,password,address from user2 where id = #{id}
</select>使用SQL語(yǔ)句中的別名功能,這樣查詢的結(jié)果實(shí)際又變?yōu)榱薸d、userName、password、address這樣幾個(gè)字段,這樣mybatis就知道哪個(gè)字段對(duì)應(yīng)哪個(gè)屬性了,就能成功轉(zhuǎn)化了。
使用mapUnderscoreToCamelCase屬性
在mybatis的配置文件中,有一個(gè)settings節(jié)點(diǎn),該節(jié)點(diǎn)中都是setting節(jié)點(diǎn),setting節(jié)點(diǎn)有一個(gè)屬性叫做mapUnderscoreToCamelCase,該屬性表示是否開(kāi)啟自動(dòng)駝峰命名規(guī)則映射,即從經(jīng)典的數(shù)據(jù)庫(kù)列名A_COLUMN到經(jīng)典Java屬性名aColumn的映射,這種方式要求我們的數(shù)據(jù)庫(kù)字段命名和JavaBean屬性命名都要非常規(guī)范才能實(shí)現(xiàn)。這個(gè)屬性的開(kāi)啟也是非常容易的,在mybatis的配置文件中,我這里實(shí)在mybatis-conf.xml文件中,添加如下代碼即可 :
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>開(kāi)啟了這個(gè)之后,在Select節(jié)點(diǎn)中我們就不需要使用別名這種方式了,直接像下面這樣寫就行了,如下:
<select id="getUser" resultType="u" parameterType="Long">
select * from user2 where id = #{id}
</select>OK,其實(shí)只要我們?cè)陂_(kāi)發(fā)中遵守命名規(guī)范,這個(gè)問(wèn)題其實(shí)很好解決的。
使用resultMap來(lái)解決
resultMap算是這個(gè)問(wèn)題的一個(gè)終極解決方案了,當(dāng)然resultMap的意義不局限于此,我們這里先說(shuō)resultMap的這個(gè)功能,resultMap可以用來(lái)描述從數(shù)據(jù)庫(kù)結(jié)果集中來(lái)加載對(duì)象,有的時(shí)候映射過(guò)于復(fù)雜,我們可以在Mapper中定義resultMap來(lái)解決映射問(wèn)題,比如還是上面那個(gè)問(wèn)題,我可以在userMapper中這樣來(lái)定義一個(gè)resultMap:
<resultMap id="userMap" type="org.sang.bean.User">
<id property="id" column="id" javaType="long" jdbcType="NUMERIC"/>
<result property="userName" column="user_name" javaType="string" jdbcType="VARCHAR"/>
<result property="password" column="password" javaType="string" jdbcType="VARCHAR"/>
<result property="address" column="address" javaType="string" jdbcType="VARCHAR"/>
</resultMap>關(guān)于這個(gè)resultMap,我說(shuō)如下幾點(diǎn):
1.首先我們給resultMap去了一個(gè)id,這個(gè)id是resultMap的唯一標(biāo)識(shí)符,我們?cè)诤竺嬉眠@個(gè)resultMap的時(shí)候就是通過(guò)這個(gè)id來(lái)引用,然后還定義了type屬性,type屬性指明了這個(gè)resultMap它對(duì)應(yīng)的是哪個(gè)JavaBean。
2.在resultMap節(jié)點(diǎn)中,id表示哪個(gè)字段代表這主鍵,result節(jié)點(diǎn)定義了普通的映射關(guān)系,這里的property表示JavaBean中的屬性名稱,column表示數(shù)據(jù)庫(kù)中的字段名稱,javaType代表JavaBean中該屬性的類型,jdbcType則表示數(shù)據(jù)庫(kù)中該字段的類型,
OK ,如此定義之后,我們只需要在select查詢的時(shí)候指定resultMap即可,如下:
<select id="getUser" resultMap="userMap" parameterType="Long">
select * from user2 where id = #{id}
</select>select多條件查詢
之前我們舉的幾個(gè)例子查詢的時(shí)候都是只有一個(gè)查詢條件,真正開(kāi)發(fā)中多條件查詢也是非常常見(jiàn)的需求,對(duì)于多條件查詢mybatis也給我們提供了相應(yīng)的方式,我們來(lái)看一下:
使用Map集合傳遞參數(shù)
我們可以將參數(shù)裝入Map集合中傳入,使用Map集合傳遞參數(shù)的話需要我在UserMapper接口中定義方法的時(shí)候參數(shù)就先設(shè)置為Map,如下:
public ArrayList<User> getUserByAddressAndName2(Map<String,String> map);
然后在userMapper.xml中將map中的數(shù)據(jù)提取出來(lái):
<select id="getUserByAddressAndName2" resultMap="userMap">
SELECT * FROM user2 WHERE address=#{address} AND user_name LIKE concat(#{username},'%')
</select>提取的方式還是通過(guò)#{XXX},只不過(guò)這里XXX代表map中數(shù)據(jù)的key。然后在使用的時(shí)候組裝map集合數(shù)據(jù),如下:
@Test
public void test3() {
SqlSession sqlSession = null;
try {
sqlSession = DBUtils.openSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
Map<String, String> map = new HashMap<String, String>();
map.put("address", "長(zhǎng)沙");
map.put("username", "趙");
List<User> list = userMapper.getUserByAddressAndName2(map);
for (User user : list) {
System.out.println(user);
}
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}構(gòu)造map傳入即可,但是在開(kāi)發(fā)中一般我們不推薦這種方式,因?yàn)閗ey容易寫錯(cuò),這種方式也不直觀,采用較多的還是后面兩種方式。
使用@Param注解
@Param注解可以把問(wèn)題進(jìn)一步簡(jiǎn)化,如下,首先在UserMapper這個(gè)接口中定義相關(guān)的方法:
public List<User> getUserByAddressAndName(@Param("username") String username, @Param("address") String address);在數(shù)據(jù)提交的過(guò)程中,mybatis會(huì)以@Param提供的名稱為準(zhǔn),如此,我們?cè)趗serMapper.xml中可以這樣來(lái)定義(注意我們我們不再需要指定參數(shù)類型):
<select id="getUserByAddressAndName" resultMap="userMap">
SELECT * FROM user2 WHERE address=#{address} AND user_name LIKE concat(#{username},'%')
</select>這樣的話參數(shù)的傳遞就更直觀一些,使用方式如下:
@Test
public void test2() {
SqlSession sqlSession = null;
try {
sqlSession = DBUtils.openSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> list = userMapper.getUserByAddressAndName("趙", "長(zhǎng)沙");
for (User user : list) {
System.out.println(user);
}
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}這種方式是我們推薦的一種方式,參數(shù)傳遞很直觀,不必像map那樣還要去考慮key到底是什么。
使用JavaBean
第二種方式按說(shuō)已經(jīng)很完美了,但是還有一種情況就是如果參數(shù)特別多的話,這樣寫起來(lái)也是非常麻煩的一件事,所以mybatis支持我們?cè)趥鲄⒌臅r(shí)候可以直接傳入對(duì)象,傳入對(duì)象的話需要我們先創(chuàng)建對(duì)象類,如下:
public class UserParams {
private String username;
private String address;
//省略getter/setter
}然后在UserMapper中定義方法,如下:
public ArrayList<User> getUserByAddressAndName3(UserParams params);
最后在userMapper.xml文件中我們直接設(shè)置parameterType為UserParams,然后引用UserParams中的屬性即可,如下:
<select id="getUserByAddressAndName3" resultMap="userMap" parameterType="org.sang.bean.UserParams">
SELECT * FROM user2 WHERE address=#{address} AND user_name LIKE concat(#{username},'%')
</select>使用方式如下:
@Test
public void test6() {
SqlSession sqlSession = null;
try {
sqlSession = DBUtils.openSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
UserParams userParams = new UserParams("趙", "長(zhǎng)沙");
List<User> list = userMapper.getUserByAddressAndName3(userParams);
for (User user : list) {
System.out.println(user);
}
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}第二種和第三種是我們?cè)陂_(kāi)發(fā)中常用的傳參方式,小伙伴們?cè)陂_(kāi)發(fā)中根據(jù)實(shí)際情況選擇合適的方式即可。
insert中的主鍵回填
可能有小伙伴不理解什么是主鍵回填,我這里簡(jiǎn)單解釋下,比如我們?cè)趧?chuàng)建表的時(shí)候設(shè)置了表的id為自增長(zhǎng)字段,我在Java代碼中存儲(chǔ)一條數(shù)據(jù)時(shí)先構(gòu)建了一個(gè)JavaBean,這個(gè)JavaBean的id屬性是為null,因?yàn)閕d不需要插入到數(shù)據(jù)庫(kù)中去 ,那么當(dāng)我將數(shù)據(jù)插入成功之后系統(tǒng)會(huì)自動(dòng)給該對(duì)象的id屬性賦值,值為剛剛插入那條數(shù)據(jù)的id,這就稱作主鍵回填。這個(gè)在我們開(kāi)發(fā)中也是非常常見(jiàn)的需求,我可能希望知道剛剛插入成功的數(shù)據(jù)的id是多少,而很多時(shí)候id可能都是按照某種既定規(guī)則去生成,我們?cè)诓迦胫安⒉恢獣?,這種時(shí)候就可以使用主鍵回填。實(shí)際上想配置主鍵回填很簡(jiǎn)單,我們先來(lái)看看UserMapper中的方法:
public int insertUser(User user);
這個(gè)方法就是普普通通的UserMapper中的方法,再來(lái)看看userMapper.xml中是怎么定義的:
<insert id="insertUser" parameterType="u" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user2(user_name,password,address) VALUES (#{userName},#{password},#{address})
</insert>首先keyProperty屬性指定了哪個(gè)是主鍵字段,useGeneratedKeys的含義則是告訴mybatis這個(gè)主鍵是否使用數(shù)據(jù)庫(kù)內(nèi)置的策略生成,OK,這樣寫了之后,我們?cè)傧驍?shù)據(jù)庫(kù)插入一條數(shù)據(jù),如下:
@Test
public void test7() {
SqlSession sqlSession = null;
try {
sqlSession = DBUtils.openSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User(null, "奧巴牛", "123456", "米國(guó)");
int i = userMapper.insertUser(user);
System.out.println("i:"+i+";id:"+user.getId());
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}注意,這里的i表示受影響的行數(shù),在這里就是插入的行數(shù),我們?cè)跇?gòu)造User對(duì)象的時(shí)候id是為null,數(shù)據(jù)插入成功之后再來(lái)打印id屬性,我們來(lái)看看結(jié)果:

插入成功之后mybatis已經(jīng)給id屬性賦值了,值即為剛剛插入數(shù)據(jù)。當(dāng)然這種我們是按照數(shù)據(jù)庫(kù)的規(guī)則自動(dòng)生成id,有的時(shí)候生成id的規(guī)則需要我們自定義,當(dāng)然,mybatis也給我們提供了相應(yīng)的方式。
insert中主鍵自定義
假設(shè)有這樣一種需求,當(dāng)我往數(shù)據(jù)庫(kù)中插入一條數(shù)據(jù)的時(shí)候,如果此時(shí)表為空,則這條數(shù)據(jù)的id我設(shè)置為1,如果表不為空,那我找到表中最大的id,然后給其加2作為即將添加數(shù)據(jù)的id,這種也算是較常見(jiàn)的需求,我們來(lái)看看怎么實(shí)現(xiàn)吧。
先在UserMapper中定義相關(guān)方法:
public int insertUser2(User user);
這個(gè)方法很普通,沒(méi)啥特殊的地方,然后在userMapper.xml中定義insert節(jié)點(diǎn),如下:
<insert id="insertUser2" parameterType="u" useGeneratedKeys="true" keyProperty="id">
<selectKey keyProperty="id" resultType="long" order="BEFORE">
SELECT if(max(id) is null,1,max(id)+2) as newId FROM user3
</selectKey>
INSERT INTO user3(id,user_name,password,address) VALUES (#{id},#{userName},#{password},#{address})
</insert>這里我們使用了selectKey來(lái)進(jìn)行了簡(jiǎn)單的處理。selectKey中的keyProperty屬性表示selectKey中的sql語(yǔ)句的查詢結(jié)果應(yīng)該被設(shè)置的目標(biāo)屬性,我們這里當(dāng)然是要設(shè)置為id了,然后我在下文好使用這個(gè)id,selectKey的resultType屬性表示查詢結(jié)果的返回類型,注意這個(gè)類型要和User類中id的類型一致,selectKey中的order=”BEFORE”表示在插入操作之前選擇主鍵,order的另一個(gè)取值A(chǔ)FTER表示執(zhí)行完插入操作之后再選擇主鍵,關(guān)于這一塊小伙伴可以參考這篇博客Mybatis 示例之 SelectKey 。OK,最后我們來(lái)看看調(diào)用:
@Test
public void test8() {
SqlSession sqlSession = null;
try {
sqlSession = DBUtils.openSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User(null, "米歇爾", "222222", "米國(guó)");
int i = userMapper.insertUser2(user);
System.out.println("i:"+i+";id:"+user.getId());
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}OK,以上就是select和insert的一些配置細(xì)則,剩下的update和delete和這兩個(gè)差不多,我就不再贅述。
本文案例下載:
本文案例GitHub地址https://github.com/lenve/JavaEETest/tree/master/Test27-mybatis5。
到此這篇關(guān)于mybatis映射器配置小結(jié)的文章就介紹到這了,更多相關(guān)mybatis映射器配置內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Spring Cloud微服務(wù)架構(gòu)下的WebSocket解決方案
這篇文章主要介紹了詳解Spring Cloud微服務(wù)架構(gòu)下的WebSocket解決方案,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12
Java中replace與replaceAll的區(qū)別與測(cè)試
replace和replaceAll是JAVA中常用的替換字符的方法,下面這篇文章主要給大家介紹了關(guān)于Java中replace與replaceAll的區(qū)別與測(cè)試,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09
java策略枚舉:消除在項(xiàng)目里大批量使用if-else的優(yōu)雅姿勢(shì)
這篇文章主要給大家介紹了關(guān)于Java徹底消滅if-else的8種方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2021-06-06
SpringCloud及Nacos服務(wù)注冊(cè)IP選擇問(wèn)題解決方法
這篇文章主要介紹了SpringCloud及Nacos服務(wù)注冊(cè)IP選擇問(wèn)題,為什么注冊(cè)的IP和真實(shí)IP不符合呢,原因是Nacos客戶端在注冊(cè)服務(wù)時(shí)會(huì)從機(jī)器網(wǎng)卡中選擇一個(gè)IP來(lái)注冊(cè),所以,當(dāng)注冊(cè)了的是非真實(shí)IP后,另一臺(tái)機(jī)器調(diào)用時(shí)是不可能調(diào)通的,知道問(wèn)題原因就是解決方法,一起看看吧2024-01-01
druid ParserException類錯(cuò)誤問(wèn)題及解決
這篇文章主要介紹了druid ParserException類錯(cuò)誤問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12

