MyBatis insert 標(biāo)簽用來定義插入語句,執(zhí)行插入操作。當(dāng) MyBatis 執(zhí)行完一條插入語句后,就會(huì)返回其影響數(shù)據(jù)庫的行數(shù)。
下面通過一個(gè)示例演示 insert 標(biāo)簽的具體用法。
1. 修改 WebsiteMapper.xml,增加插入語句,代碼如下。
<!-- 增加網(wǎng)站信息 --> <insert id="addWebsite" parameterType="string"> insert into website(name) values(#{name}) </insert>
2. 在 WebsiteMapper 接口中定義一個(gè) add() 方法,代碼如下。
public int addWebsite(String name);
參數(shù)為 Sting 類型的字符串;返回值為 int 類型,即執(zhí)行 SQL 后,插入記錄的行數(shù)。
3. 測(cè)試代碼如下。
//插入 name 為編程幫4 的記錄 String name = "編程幫4"; int i = websiteMapper.addWebsite(name); System.out.println("共插入了 " + i + " 條記錄");
4. 執(zhí)行測(cè)試代碼,控制臺(tái)輸出如下。
共插入了 1 條記錄
insert 標(biāo)簽中常用的屬性如下表。
屬性名稱 | 描述 | 備注 |
---|---|---|
id | 它和 Mapper 的命名空間組合起來使用,是唯一標(biāo)識(shí)符,供 MyBatis 調(diào)用 | 如果命名空間+ id 不唯一,那么 MyBatis 拋出異常 |
parameterType | 傳入 SQL 語句的參數(shù)類型的全限定名或別名,它是一個(gè)可選屬性。 | 支持基本數(shù)據(jù)類型和 JavaBean、Map 等復(fù)雜數(shù)據(jù)類型 |
keyProperty | 該屬性的作用是將插入操作的返回值賦給 PO 類的某個(gè)屬性,通常為主鍵對(duì)應(yīng)的屬性。如果是聯(lián)合主鍵,可以將多個(gè)值用逗號(hào)隔開。 | - |
useGeneratedKe | 該屬性用來設(shè)置,是否使用 JDBC 提供的 getGenereatedKeys() 方法,獲取數(shù)據(jù)庫內(nèi)部產(chǎn)生的主鍵并賦值到 keyProperty 屬性設(shè)置的請(qǐng)求對(duì)象的屬性中,例如 MySQL、SQL Server 等自動(dòng)遞增的字段,其默認(rèn)值為 false。 | 該屬性值設(shè)置為 true 后,會(huì)將數(shù)據(jù)庫生成的主鍵回填到請(qǐng)求對(duì)象中,以供其他業(yè)務(wù)使用。 |
flushCache | 該屬性用于設(shè)置執(zhí)行該操作后,是否會(huì)清空二級(jí)緩存和本地緩存,默認(rèn)值為 true。 | - |
timeout | 該屬性用于設(shè)置執(zhí)行該操作的最大時(shí)限,如果超時(shí),就拋異常。 | - |
databaseId | 取值范圍 oracle、mysql 等,表示數(shù)據(jù)庫廠家;元素內(nèi)部可通過 <if test="_databaseId = 'oracle'"> 來為特定數(shù)據(jù)庫指定不同的 sql 語句。 | MyBatis 可以根據(jù)不同的數(shù)據(jù)庫廠商執(zhí)行不同的語句,這種多廠商的支持是基于映射語句中的 databaseId 屬性。 MyBatis 會(huì)加載不帶 databaseId 屬性和帶有匹配當(dāng)前數(shù)據(jù)庫 databaseId 屬性的所有語句。 如果同時(shí)找到帶有 databaseId 和不帶 databaseId 的相同語句,則后者會(huì)被舍棄。 |
keyColumn | 該屬性用于設(shè)置第幾列是主鍵,當(dāng)主鍵列不是表中的第 1 列時(shí),就需要設(shè)置該屬性。如果是聯(lián)合主鍵,可以將多個(gè)值用逗號(hào)隔開。 | - |
注意:insert 標(biāo)簽中沒有 resultType 屬性,只有查詢操作才需要對(duì)返回結(jié)果類型進(jìn)行相應(yīng)的指定。
在上面的示例中,我們?cè)诓迦胝Z句中只使用了一個(gè) String 類型的參數(shù),而在實(shí)際的開發(fā)過程中,我們的插入語句往往需要使用多個(gè)參數(shù),Mybatis 為我們提供以下 3 種方式,來實(shí)現(xiàn)給映射器傳遞多個(gè)參數(shù):
使用 Map 傳遞參數(shù)
使用注解傳遞參數(shù)
使用 JavaBean 傳遞參數(shù)
我們可以將參數(shù)封裝到一個(gè) Map 對(duì)象中,然后傳遞給 MyBatis 的映射器,示例如下。
1. 在 WebsiteMapper 接口中,定義一個(gè) addWebsiteByMap() 方法,并使用 Map 傳遞參數(shù),方法如下。
int addWebsiteByMap(Map<String, String> params);
2. 在 WebsiteMapper.xml 中,使用 insert 標(biāo)簽定義一條插入語句,并接收通過 Map 傳遞的參數(shù),配置如下。
<!--接收 Map 參數(shù)--> <insert id="addWebsiteByMap" parameterType="map"> insert into Website (name, url) values (#{name}, #{url}) </insert>
3. 測(cè)試代碼如下。
Map<String, String> params = new HashMap<>(); params.put("name", "編程幫"); params.put("url", "http://www.soo66.com/"); int i = websiteMapper.addWebsiteByMap(params); System.out.println("通過 Map 成功向數(shù)據(jù)庫中添加了 " + i + " 條記錄");
4. 執(zhí)行測(cè)試代碼,控制臺(tái)輸出如下。
Map<String, String> params = new HashMap<>(); params.put("name", "編程幫"); params.put("url", "http://www.soo66.com/"); int i = websiteMapper.addWebsiteByMap(params); System.out.println("通過 Map 成功向數(shù)據(jù)庫中添加了 " + i + " 條記錄");
通過 Map 成功向數(shù)據(jù)庫中添加了 1 條記錄
我們還可以使用 MyBatis 提供的 @Param 注解給注解器傳遞參數(shù),示例代碼如下。
1. 在 WebsiteMapper 接口中,定義一個(gè) addWebsiteByParam() 方法,并使用 @Param 注解傳遞參數(shù),方法如下
int addWebsiteByParam(@Param("name") String name, @Param("url") String url);
2. 在 WebsiteMapper.xml 中使用 insert 標(biāo)簽定義一條插入語句,并接收通過 @Param 注解傳遞的參數(shù),配置如下。
<!--接收 @Param 注解傳遞的參數(shù)--> <insert id="addWebsiteByParam"> insert into Website (name, url) values (#{name}, #{url}) </insert>
3. 測(cè)試代碼如下。
int i = websiteMapper.addWebsiteByParam("bianchengbang", "www.soo66.com"); System.out.println("通過 @Param 注解成功向數(shù)據(jù)庫中添加了 " + i + " 條記錄");
4. 執(zhí)行測(cè)試代碼,控制臺(tái)輸出如下。
通過 @Param 注解成功向數(shù)據(jù)庫中添加了 1 條記錄
在參數(shù)過多的情況下,我們可以將參數(shù)通過 setter 方法封裝到 JavaBean(實(shí)體類)對(duì)象中 ,傳遞給映射器。
1. 在 WebsiteMapper 接口中,定義一個(gè) addWebsiteByJavaBean() 方法,并使用 JavaBean 傳遞參數(shù),方法如下。
int addWebsiteByJavaBean(Website website);
2. 在 WebsiteMapper.xml 中使用 insert 標(biāo)簽定義一條插入語句,并接收通過 JavaBean 傳遞的參數(shù),配置如下。
<!--接收通過 JavaBean 傳遞的參數(shù)--> <insert id="addWebsiteByJavaBean" parameterType="net.biancheng.www.po.Website"> insert into Website (name, url) values (#{name}, #{url}) </insert>
3. 測(cè)試代碼如下。
//創(chuàng)建 JavaBean 對(duì)象 Website website = new Website(); //通過 setter 方法將參數(shù)封裝 website.setName("編程幫 JavaBean"); website.setUrl("www.soo66.com"); int i = websiteMapper.addWebsiteByJavaBean(website); System.out.println("通過 JavaBean 成功向數(shù)據(jù)庫中添加了 " + i + " 條記錄");
4. 執(zhí)行測(cè)試代碼,控制臺(tái)輸出如下。
通過 JavaBean 成功向數(shù)據(jù)庫中添加了 1 條記錄
以上 3 種方式的區(qū)別如下:
使用 Map 傳遞參數(shù)會(huì)導(dǎo)致業(yè)務(wù)可讀性的喪失,繼而導(dǎo)致后續(xù)擴(kuò)展和維護(hù)的困難,所以在實(shí)際應(yīng)用中我們應(yīng)該果斷廢棄該方式。
使用 @Param 注解傳遞參數(shù)會(huì)受到參數(shù)個(gè)數(shù)的影響。當(dāng) n≤5 時(shí),它是最佳的傳參方式,因?yàn)樗又庇^;當(dāng) n>5 時(shí),多個(gè)參數(shù)將給調(diào)用帶來困難。
當(dāng)參數(shù)個(gè)數(shù)大于 5 個(gè)時(shí),建議使用 JavaBean 方式。
我們知道,MySQL、SQL Server 等數(shù)據(jù)庫表可以采用自動(dòng)遞增的字段作為其主鍵,當(dāng)向這樣的數(shù)據(jù)庫表插入數(shù)據(jù)時(shí),即使不指定自增主鍵的值,數(shù)據(jù)庫也會(huì)根據(jù)自增規(guī)則自動(dòng)生成主鍵并插入到表中。
一些特殊情況下,我們可能需要將這個(gè)剛剛生成的主鍵回填到請(qǐng)求對(duì)象(原本不包含主鍵信息的請(qǐng)求對(duì)象)中,供其他業(yè)務(wù)使用。此時(shí),我們就可以通過在 insert 標(biāo)簽中添加 keyProperty 和 useGeneratedKeys 屬性,來實(shí)現(xiàn)該功能。
下面我們通過一個(gè)示例,來演示主鍵(自動(dòng)遞增)回填功能。
1. 為 WebsiteMapper.xml 中 id 為 addWebsite 的 insert 標(biāo)簽添加 keyProperty 和 useGeneratedKeys 屬性,具體代碼如下:
<!--添加一個(gè)網(wǎng)站信息,成功后將主鍵值返回填給id(po的屬性)--> <insert id="addWebsite" parameterType="net.biancheng.po.Website" keyProperty="id" useGeneratedKeys="true"> insert into Website (name,url) values(#{name},#{url}) </insert>
2. 測(cè)試代碼如下:
// 添加一個(gè)網(wǎng)站信息 Website addsite = new Website(); //插入的對(duì)象中不包含主鍵 id addsite.setName("編程幫"); addsite.setUrl("http://www.soo66.com/"); //執(zhí)行插入 int num = websiteMapper.addWebsite(addsite); System.out.println("添加了 " + num + " 條記錄"); //獲取回填的主鍵 System.out.println("添加記錄的主鍵是:" + addsite.getId());
3. 執(zhí)行測(cè)試代碼,控制臺(tái)輸出如下。
添加了 1 條記錄 添加記錄的主鍵是:3
如果在實(shí)際項(xiàng)目中,若數(shù)據(jù)庫不支持主鍵自動(dòng)遞增(例如 Oracle),或者取消了主鍵自動(dòng)遞增的規(guī)則,我們可以使用 MyBatis 的 <selectKey> 標(biāo)簽自定義生成主鍵,具體配置代碼如下。
<!-- 添加一個(gè)網(wǎng)站,#{name}為 net.biancheng.po.Website 的屬性值 --> <insert id="insertWebsite" parameterType="net.biancheng.po.Website"> <!-- 先使用selectKey標(biāo)簽定義主鍵,然后再定義SQL語句 --> <selectKey keyProperty="id" resultType="Integer" order="BEFORE"> select if(max(id) is null,1,max(id)+1) as newId from Website </selectKey> insert into Website (id,name,url) values(#{id},#{name},#{url}) </insert>
<selectKey> 標(biāo)簽中屬性說明如下:
keyProperty:用于指定主鍵值對(duì)應(yīng)的 PO 類的屬性。
order:該屬性取值可以為 BEFORE 或 AFTER。BEFORE 表示先執(zhí)行 <selectKey> 標(biāo)簽內(nèi)的語句,再執(zhí)行插入語句;AFTER 表示先執(zhí)行插入語句再執(zhí)行 <selectKey> 標(biāo)簽內(nèi)的語句。