Spring mvc整合Mybatis,選擇性儲存物件欄位資料
前言
我們平時使用mybatis儲存物件資料時,經常可能只是修改其中某一倆個欄位的值,這個時候,我們為了減少資料庫更新帶來的效能、行鎖等不必要的消耗,可能會重新寫一個介面,只負責修改需要修改的值。
但是,隨著業務系統的變更,業務欄位的增加,越來越多的欄位需要根據不同的業務場景和業務操作,需要更改的欄位越來越多,相應的介面也越來越多,甚至有些方法都不再使用,刪也不敢刪,留著又影響程式碼閱讀。
所以,如果有一個方法,可以做到“[只對我設定值的欄位才進行修改][6]”,那該多好。
很慶幸,mybatis為我們提供了xml格式的條件判斷語句,我們只需要驗證 field != null 即可。
但是也很不幸,這裡面有些坑,比如:int型別值、char型別、double型別,這些型別是有預設值的,並且不會等於null。
那麼基於這個問題,下面是我對這件事做的實驗。
準備
研究欄位型別
本次實驗僅研究了常見的10種資料型別,下面是資料庫型別與Java型別的對比
JDBC Type ———- Java Type
CHAR —————-> String
VARCHAR ———> String
INTEGER ———–> int
TINYINT ————–> byte
DOUBLE ————> double
DATE —————–> java.sql.Date
TIMESTAMP ——–> java.sql.Timestamp
NUMERIC ———–> java.math.BigDecimal
DECIMAL ————> java.math.BigDecimal
BOOLEAN ———-> boolean
建立資料庫表
為了實驗,本次採用了mysql資料庫作為實驗物件,資料表對應的研究欄位型別與java欄位型別對應如下。
對應關係如下,Java類UserPO
Field——-Type—————-Java-Type–Field
id———-int(11)————private-int-id;
userid——char(32)———–private-char-userid;
activityid–char(32)———–private-Character-activityid;
openid——char(27)———–private-String-openid;
user_name—varchar(50)——–private-String-user_name;
age———int(11)————private-int-age;
xueli——-int(11)————private-Integer-xueli;
score——-double(11,2)——-private-double-score;
points——double(11,2)——-private-Double-points;
sex———tinyint(1)———private-short-sex;
status——tinyint(1)———private-Short-status;
birthday—-date—————private-Date-birthday;
createtime–datetime———–private-Date-createtime;
amount——decimal(11,2)——private-BigDecimal-amount;
price——-decimal(11,2)——private-Double-price;
disabled—-tinyint(1)———private-Boolean-disabled;
deleted—–tinyint(1)———private-Boolean-deleted;
使用者物件
public class UserPO {
private int id;
private char userid;
private Character activityid;
private String openid;
private String user_name;
private int age;
private Integer xueli;
private double score;
private Double points;
private short sex;
private Short status;
private Date birthday;
private Date createtime;
private BigDecimal amount;
private Double price;
private Boolean disabled;
private Boolean deleted;
}
UserMapper物件
@Mapper
public interface UserMapper {
int insertSelective(UserPO po);
}
UserMapper.xml
<mapper namespace="com.ansitech.study.web.mapper.UserMapper">
<insert id="insertSelective">
insert into t_user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="userid != null">userid,</if>
<if test="activityid != null">activityid,</if>
<if test="openid != null">openid,</if>
<if test="user_name != null">user_name,</if>
<if test="age != null">age,</if>
<if test="xueli != null">xueli,</if>
<if test="score != null">score,</if>
<if test="points != null">points,</if>
<if test="sex != null">sex,</if>
<if test="status != null">status,</if>
<if test="birthday != null">birthday,</if>
<if test="createtime != null">createtime,</if>
<if test="amount != null">amount,</if>
<if test="price != null">price,</if>
<if test="disabled != null">disabled,</if>
<if test="deleted != null">deleted,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="userid != null">#{userid,jdbcType=CHAR},</if>
<if test="activityid != null">#{activityid,jdbcType=CHAR},</if>
<if test="openid != null">#{openid,jdbcType=CHAR},</if>
<if test="user_name != null">#{user_name,jdbcType=VARCHAR},</if>
<if test="age != null">#{age,jdbcType=INTEGER},</if>
<if test="xueli != null">#{xueli,jdbcType=INTEGER},</if>
<if test="score != null">#{score,jdbcType=DOUBLE},</if>
<if test="points != null">#{points,jdbcType=DOUBLE},</if>
<if test="sex != null">#{sex,jdbcType=TINYINT},</if>
<if test="status != null">#{status,jdbcType=TINYINT},</if>
<if test="birthday != null">#{birthday,jdbcType=DATE},</if>
<if test="createtime != null">#{createtime,jdbcType=TIMESTAMP},</if>
<if test="amount != null">#{amount,jdbcType=NUMERIC},</if>
<if test="price != null">#{price,jdbcType=DECIMAL},</if>
<if test="disabled != null">#{disabled,jdbcType=BOOLEAN},</if>
<if test="deleted != null">#{deleted,jdbcType=BOOLEAN},</if>
</trim>
</insert>
</mapper>
說明:
大家應該也看到了,為了測試,我給每種研究型別建了2個欄位,對應Java型別的簡單型別和物件型別。
下面給大家看下呼叫程式碼:
UserPO po = new UserPO();
userMapper.insertSelective(po);
對,你沒看錯,我就是直接插入的,沒有設定任何值。
那麼結果如何?
首先,程式的列印SQL日誌
==> Preparing: insert into t_user ( userid , age , score , sex ) values ( ?, ?, ?, ? )
==> Parameters: (String), 0(Integer), 0.0(Double), 0(Short)
結果很明顯,所有簡單型別判斷!=null都是無效的。
再看資料庫表資料
果然,資料已經有值了,這絕對不是資料表字段的預設值,見下圖。
總結
如果想選擇性插入或更新資料,請把物件中的簡單欄位型別改為物件型別。