【MyBatis】多對多條件下插入中間表(使用insert標籤的屬性)
文章目錄
需求
我的資料庫中有兩張表,一張是Blog表,一張是Type表,分別代表了部落格和部落格類別,它們之間是多對多關係,它們由一張中間表blog_type維護。
(簡單起見,blog表只有兩個資料,id和title。type表只有id和name)
那麼需求就是:
現在我想插入一條Blog資料,因為blog和type是多對多關係,想插入其中一個數據,就得維護他們之間那個中間表blog_type的關係(插入中間表字段)。
解決方案
那麼我能想到的解決方案是:
寫兩段insert標籤,第一段sql語句插入blog表,第二段sql語句插入insert表:
<insert id="insertBlogWithoutType" parameterType="blog">
insert into t_blog (title)
values (#{title});
</insert>
<insert id="insertBlog_Type">
insert into blog_type (bid, tid) values(#{blog.id},#{type.id})
</insert>
但是這麼做會有它的問題
由於blog表id為自增,所以我並沒有插入id。如何在第二個insert查詢語句中獲取剛剛插入的id呢?
經過多方查詢我發現瞭解決方案:
要用到MyBatis中insert標籤的三個屬性:
(內容引自MyBatis 多對多 中間表插入資料)
useGeneratedKeys (僅對 insert 和 update 有用)這會令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法來取出由資料庫內部生成的主鍵(比如:像 MySQL 和 SQL Server 這樣的關係資料庫管理系統的自動遞增欄位),預設值:false。
keyProperty (僅對 insert 和 update 有用)唯一標記一個屬性,MyBatis 會通過 getGeneratedKeys 的返回值或者通過 insert 語句的 selectKey 子元素設定它的鍵值,預設:unset。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。
keyColumn (僅對 insert 和 update 有用)通過生成的鍵值設定表中的列名,這個設定僅在某些資料庫(像 PostgreSQL)是必須的,當主鍵列不是表中的第一列的時候需要設定。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。
重新生成的程式碼如下所示:
<insert id="insertBlogWithoutType" parameterType="blog" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
insert into t_blog (title)
values (#{title});
</insert>
<insert id="insertBlog_Type">
insert into blog_type (bid, tid) values(#{blog.id},#{type.id})
</insert>
注意!keyProperty是Java物件的屬性名!不是資料庫表中欄位名!
測試
編寫Dao層
//分成兩個方法,但是他們兩個將在Service層合二為一
int insertBlogWithoutType(Blog blog);
int insertBlog_Type(@Param("blog")Blog blog, @Param("type")Type type);
Dao層就是對應的前面mapper檔案裡的兩個方法
Service層
public void insertBlog(Blog blog, List<Type> types) {
blogDao.insertBlogWithoutType(blog);
for (Type type : types) {
blogDao.insertBlog_Type(blog, type);
}
}
這裡的意思是,先插入一個傳進來的blog(第一個引數)。然後插入之後根據插進來的blog的主鍵(blog的id)和傳入的type的主鍵(type的id),插入中間表。
Test類
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
BlogService blogServiceImpl = (BlogService) context.getBean("BlogServiceImpl");
//設定blog
Blog blog = new Blog();
blog.setTitle("【MyBatis】多對多條件下插入中間表(使用insert標籤的屬性)");
//設定該blog對應的type
List<Type> types = new ArrayList<Type>();
types.add(new Type(1,"資料庫"));
types.add(new Type(2,"Debug專題"));
blogServiceImpl.insertBlog(blog, types);
}
可以看到,設定blog的時候,並沒有設定blog的id屬性,但是呼叫insertBlog時,插入中間表卻已經知道了blog的id屬性。這就是MyBatis中insert標籤的三個屬性的作用了!
執行完上面的程式碼,資料庫裡既插入了一條新的blog,又維護了他們之間那個中間表blog_type的關係(插入了中間表),至此問題解決。