在MYSQL和MyBatis中踩過的坑和小技巧

1. sum()和count()使用場景不對致使出錯:java

     count(*)、count(1)、count(0)就是指絕對的行數,哪怕某行全部字段所有爲null也會計算在內。count(1)和count(*)相比,innodb來講count(*)效率低。mysql

     若是count(列名)查詢出來的結果就是查出列名中不爲null的行數;spring

     sum(列名)對指定列名進行求和sql

2. 比較好用的一些函數數據庫

    2.1 CONCAT_WS和CONCAT比較舉例:apache

函數 NULL 空字符串'' 小結
CONCAT SELECT CONCAT('First name',NULL,'Last Name') AS TEST; SELECT CONCAT('First name','','Last Name') AS TEST2; 默認拼接的時候沒有分隔符,直接拼接起來
CONCAT_WS SELECT CONCAT_WS(',','First name',NULL,'Last Name') AS TEST; SELECT CONCAT_WS(',','First name','','Last Name') AS TEST2; 拼接的內容之間使用第一個參數提供的分隔符分隔。若是想要直接拼接,可是須要忽略Null的話,可使用空字符串作分隔符。效果就和CONCAT()同樣了

    2.2 GREATEST()和LEAST()mybatis

3. MyBatis把int類型的0處理成空串’’和mysql處理空串’’爲0的問題,在Mybatis的Mapper中整數類型條件該如何判斷?app

    當數據庫字段類型是整數,若是參數變量爲空字符串或者NULL,Mybatis會自動將參數賦值0,因此若是要判斷整數參數的多種狀態在傳遞數值到Mapper以前就要判斷是否爲空字符串和NULL並將相應的狀態數值賦值給該參數,不然參數值等於空字符串、NULL和0獲得的結果是同樣的。函數

    通常狀況下,涉及到int類型的操做的時候,在Service中會統一把數字類型先變成字符串類型,而後再傳遞到Mapper中操做。spa

4. 時間戳的使用

在建立新記錄的時候把這個字段設置爲當前時間,但之後修改時,再也不刷新它(能夠給createtime使用這個):TIMESTAMP DEFAULT CURRENT_TIMESTAMP

在建立新記錄和修改現有記錄的時候都對這個數據列刷新(能夠給update使用這個):

 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

5. Mysql中字符的定義

    1. char和varchar限制的是字符,而不是字節。對不一樣的字符集來講,字符和字節的關係是不必定的。

    2. 而且也不能按照換算關係換算好比一個漢字在utf8中用三個字節表示,那麼換算成英語應該是對應三個英文字母。這種換算是錯誤的。若是聲明瞭varchar(2)那麼放中文漢字是兩個漢字,放英文字母一樣是兩個

6. 在使用resultMap的時候,要把ID寫在第一行,不然的話,就會報錯。

<resultMap id="getPhysicalItemMsgList" type="map" autoMapping="false">

    <id property="TEST_ID" column="TEST_ID" /> <!-- 這裏不能和下面的一行調換位置-->

    <result property="TEST_1" column="TEST_1" />

    <collection property="TEST_LIST" javaType="ArrayList" ofType="map">

        <result property="TEST_LIST1" column="TEST_LIST1"/>

    </collection>

</resultMap>

緣由能夠經過查看resultMap的定義發現resultMap規定了排序,須要按照定義來排序才能解析經過,而後執行

<!ELEMENT resultMap (constructor?,id*,result*,association*,collection*, discriminator?)>
<!ATTLIST resultMap
id CDATA #REQUIRED
type CDATA #REQUIRED
extends CDATA #IMPLIED
autoMapping (true|false) #IMPLIED
>

7. 通常狀況在Mapper中判斷參數是否爲空的時候是字符串居多,今天趕上須要判斷list類型的的參數是否爲空,依然習慣性的使用了下面的寫法:

<if test="TEST_LIST != '' and TEST_LIST != null">
    CT.TEST IN
    <foreach collection="TEST_LIST" index="index" item="item" separator="," open="(" close=")">
       #{item.test}
    </foreach>    
</if>

結果就報錯了下面的錯誤:

Caused by: org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.ArrayList and java.lang.String
### Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.ArrayList and java.lang.String

最後,改爲如下寫法:

<if test="TEST_LIST != '' and TEST_LIST.size()>0">
    CT.TEST IN
    <foreach collection="TEST_LIST" index="index" item="item" separator="," open="(" close=")">
       #{item.test}
    </foreach>    
</if>

搞定。

8. 關於時間列表排序或者比較大小的問題

      要想對一系列的時間進行排序,在排序以前要統一用date_format()把時間的格式轉一下。不然的話,排序出來的順序可能會出現錯誤。

9. 在MySQL中使用union的時候,若是緊挨着union的內層進行排序的話,是沒有做用的

10. 更新一張表,限制條件也是從要更新的表裏面抽取的。這是若是按照常規的sql來寫。就會出現語法錯誤,執行不下去,須要變成下面的這種寫法

-- 更新同一張表的寫法
UPDATE BLOOD_PRESSURE_RECORD A1,
    -- 從表中查出條件
    (SELECT 
        MIN(BLOOD_PRESSURE_RECORD_KEY_ID) AS BLOOD_PRESSURE_RECORD_KEY_ID
    FROM
        BLOOD_PRESSURE_RECORD
    WHERE
        HYPERTENSION_RECORD_KEY_ID = 14) A2 
SET 
    A1.SYSTOLIC_PRESSURE = 222,
    A1.DIASTOLIC_PRESSURE = 321,
    A1.MEASURE_DATE = '2016-10-12',
    A1.MEASURE_DOCTOR = '123',
    A1.EDITOR_ID = 34,
    A1.EDITOR_NAME = '醫生一號',
    A1.UPDATE_TIME = NOW()
WHERE
    A1.IS_ENABLE = 1
        AND A1.BLOOD_PRESSURE_RECORD_KEY_ID = A2.BLOOD_PRESSURE_RECORD_KEY_ID
相關文章
相關標籤/搜索