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

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

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

