mybatis 標籤動態增刪改查
mybatis 《foreach》
有的時候在專案中需要查詢某個列表時,可能會在程式碼中進行巢狀迴圈再取值,其實mybatis提供了這麼一個標籤,可以在SQL中進行迴圈(是不是很酸爽)
先來了解一下foreach
這個標籤有哪些元素:
- item
- 表示集合中每一個元素進行迭代時的別名
- index
- 指定一個名字,用於表示在迭代過程中,每次迭代到的位置
- open
- 表示該語句以什麼開始
- separator
- 表示在每次進行迭代之間以什麼符號作為分隔符
- close
- 表示以什麼結束
- collection
- 被迴圈的集合或者陣列
注意
在使用foreach的時候最關鍵的也是最容易出錯的就是collection屬性,該屬性是必須指定的,但是在不同情況下,該屬性的值是不一樣的,主要有一下3種情況:
如果傳入的是單引數且引數型別是一個List的時候,collection屬性值為list
如果傳入的是單引數且引數型別是一個array陣列的時候,collection的屬性值為array
如果傳入的引數是多個的時候,我們就需要把它們封裝成一個Map或者Object。
實戰
話不多說,看程式碼,首先是mybatis的XML如何寫,拿動態建立表為例子,什麼是動態建立表,就是可以隨便生成表名,欄位是傳入進來的集合陣列,根據這個陣列內容來建立欄位
<update id="createTable" parameterType="java.util.HashMap">
CREATE TABLE IF NOT EXISTS ed_temp_${tableName}(
id VARCHAR(32) NOT NULL,
log_id VARCHAR(32),
state INT,
message VARCHAR(255)
<foreach collection="list" item="column" open="," separator="VARCHAR(255),"
close="VARCHAR(255), PRIMARY KEY (id)">
${column.name}
</foreach>
) ENGINE = InnoDB DEFAULT CHARSET = utf8;
</update>
這個<foreach>
看出,我傳入的叫一個list的集合,別名叫column,從,
開始,因為上面message少個逗號,中間用VARCHAR(255),
看Mapper類
/**
* 動態建立表
*/
void createTable(HashMap<String , Object> map);
看實現
/**
* 建立表
* @param templateId 模板id
*/
private void createTable(String templateId){
List<EdTemplateField> fields = edTemplateFieldMapper.findByTemplate(templateId);
List<EdFieldColumns> columns = new ArrayList<>();
HashMap<String,Object> map = new HashMap<>(16);
map.put("tableName",templateId);
for (EdTemplateField field : fields) {
columns.add(edFieldColumnsMapper.findByField(field.getId()).get(0));
}
map.put("list",columns);
edTemplateMapper.createTable(map);
}
邏輯是這樣的,通過傳入的ID,去尋找所需要的值,再建立一個List和一個Map,將表名放進來,在將需要的陣列放進來,呼叫mapper的方法,最後就能成功建立一張動態表
往這個動態表裡插入資料的方式也用到了<foreach>
,應該說不得不用,不然怎麼插入,又不知道表名又沒有實體類
XML
<insert id="tableInsert" parameterType="java.util.HashMap">
INSERT INTO ed_temp_${tableName}(
id,log_id,state,message
<foreach collection="columns" item="column" open="," separator="," >
${column.name}
</foreach>
)VALUES(
<foreach collection="values" item="value" open="REPLACE(UUID(),'-','')," separator="," >
#{value}
</foreach>
)
</insert>
兩個<foreach>
標籤,一個是欄位,剛剛那個動態建表的欄位,一個是值
mapper類
/**
* 動態插入
* @param map
*/
void tableInsert(HashMap<String,Object> map);
實現方法
/**
* 儲存資料到臨時表
* @param templateId 模板id
* @param list 資料集合
* @param hearTitle 資料對應的欄位
*/
private void tableInsert(String templateId,List<String> list,List<String> hearTitle){
List<EdFieldColumns> columns = new ArrayList<>();
HashMap<String,Object> map = new HashMap<>(16);
map.put("tableName",templateId);
for (String s : hearTitle) {
columns.add(edFieldColumnsMapper.findByTemplateIdAndName(s,templateId));
}
map.put("columns",columns);
map.put("values",list);
edTemplateMapper.tableInsert(map);
}
說明
其餘的類程式碼就不貼了,邏輯是這樣的,建立一個放欄位的集合和傳入的map,集合的值必須要和欄位對應的上,不然插錯欄位值那就很尷尬,所以必須要通過動態建立的欄位和值的順序是一樣的,比如第一個建立了name那插入的第一個就是name,這個意思,所以這裡是根據順序,先排好了欄位,放入map裡,再將要放入動態表的值放進來,進行mapper操作
有了建表以及插入,當然少不了刪除和更新
刪除表的xml
<update id="deleteTable" parameterType="java.lang.String">
DROP TABLE ${tempTable}
</update>
<delete id="deleteTemporary">
DELETE
FROM
${tableName}
WHERE
id = #{id}
</delete>
用於來刪除不需要的表,以及刪除資料
void deleteTable(@param(value = "tempTable") String tempTable);
void deleteTemporary(@Param("tableName") String tableName,
@Param("id") String id);
這是mapper介面的寫法,傳入要刪除的表名就可以
更新的XML
<update id="updateTemporary">
UPDATE ${tableName}
SET
<foreach collection="dataMap" index="key" item="value" separator="," >
${key} = #{value}
</foreach>
WHERE
id = #{id}
</update>
對應的mapper介面
void updateTemporary(@Param("tableName") String tableName,
@Param("id") String id,
@Param("dataMap") HashMap dataMap);