mybatis插入資料後主鍵回填的幾種方式
主鍵回填一般是插入一條資料,id設為自增,當插入一條記錄時,並返回該記錄id值
一、JDBC原生寫法:
public int insert(Person person) { Connection con = null; PreparedStatement ps = null; ResultSet rs = null; con = DBUtils.getConnection(); ps = con.prepareStatement("INSERT INTO person(username,password,money) VALUES(?,?,?)", PreparedStatement.RETURN_GENERATED_KEYS); ps.setObject(1, person.getUsername()); ps.setObject(2, person.getPassword()); ps.setObject(3, person.getMoney()); int i = ps.executeUpdate(); rs = ps.getGeneratedKeys(); int id = -1; if (rs.next()) { id = rs.getInt(1); } return id; }
和普通的插入 SQL 不同之處主要體現在兩個地方:
- 第一個是構造 PreparedStatement 時,多了一個引數,指定了需要主鍵回填。
- 在更新操作執行完成之後,呼叫 getGeneratedKeys ,然後又會獲取到一個 ResultSet 物件,從這個遊標集中就可以獲取到剛剛插入資料的id。
二、mybatis方式:
1、 方式一
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id"> insert into t_user (name,age) values (#{name},#{age}); </insert>
這種方式就是在插入節點上新增 useGeneratedKeys 屬性,同時設定接收回傳主鍵的屬性。配置完成後,我們執行一個插入操作,插入時傳入一個物件,插入完成後,這個物件的 id 就會被自動賦值,值就是剛剛插入成功的id。
2、方式二
<insert id="insertUser"> <selectKey keyProperty="id" resultType="java.lang.Integer"> SELECT LAST_INSERT_ID() </selectKey> insert into t_user (name,age) values (#{name},#{age}); </insert>
這種方式是在 insert 節點中新增 selectKey 來實現主鍵回填,實際上這種方式的功能更加豐富,因為 selectKey 節點中的 SQL 我們既可以在插入之前執行,也可以在插入之後執行(通過設定節點的 Order 屬性為 AFTER 或者 BEFORE 可以實現),具體什麼時候執行,還是要看具體的需求,如果是做主鍵回填,我們當然需要在插入 SQL 執行之後執行 selectKey 節點中的 SQL。
注意第二種方式一樣也要通過設定 keyProperty 來指定將查詢到的資料繫結到哪個屬性上。
三、註解的方式:
註解可用於mapper介面方法上
1、@Options註解
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
useGeneratedKeys:開啟主鍵回填
keyProperty:表示物件中的成員變數
keyColumn:表示資料庫中的列名
2、@SelectKey註解
@SelectKey(statement = "select last_insert_id()", keyProperty = "id", before = false, resultType = long.class)
statement是要執行的SQL語句,它的返回值通過resultType來指定
before:指select語句是否在insert之前執行
select last_insert_id()也可以換成@@identity,效果一樣
四、擴充套件:
@Options註解:
- 使用場景一:快取
@Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 1000)
useCache = true表示將會快取本次查詢結果,以提高下次查詢速度
flushCache = Options.FlushCachePolicy.FALSE表示查詢時不重新整理快取
timeout = 10000表示查詢結果快取10000秒 - 使用場景二:主鍵回填