1. 程式人生 > >Spring mvc整合Mybatis,選擇性儲存物件欄位資料

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都是無效的。

再看資料庫表資料
這裡寫圖片描述
果然,資料已經有值了,這絕對不是資料表字段的預設值,見下圖。
這裡寫圖片描述

總結

如果想選擇性插入或更新資料,請把物件中的簡單欄位型別改為物件型別。