mysql字段默認值不生效的問題解決(上)


在項目中使用mybatis做為持久層框架,mysql數據庫。項目上線前,DBA要求我們將每張數據庫表中的字段都設置默認值和not null。之前項目中有一些insert語句是將表中所有字段都列出來,然后把它做為一個通用的插入語句來使用。舉個簡單的例子:假如一張數據庫表blog中有如下幾個字段:id,title,content,author,除id外,每個字段都設置了默認值Empty String(空字符串),寫的一個insert語句是這樣的: 


Java代碼   收藏代碼
  1. <insert id="addOneBlog" parameterType="main.Blog">  
  2.     insert into blog(title,author,content)  
  3.     values(#{title},#{author},#{content})  
  4. </insert>  



    原以為有這么一個insert語句就萬事大吉了,我們以為,以后做插入操作的時候,無論有多少個字段,都使用這一個insert語句,如果字段沒有值,就會被賦值為mysql字段的默認值。。。 

    但事實證明,根本不是這樣的。 

    當我們只給title字段賦值,然后執行一個insert語句時,mybatis馬上報出這樣的異常: 


Java代碼   收藏代碼
  1. Caused by: com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Column 'content' cannot be null  



    顯然,所有字段規定了not null,看來按照這種insert的方法,未賦值的字段並沒有賦值為mysql的默認值。 

    那么如果把數據庫字段的not null限制去掉呢? 

    再次執行剛才的insert操作,這次沒有拋出異常,但查看數據庫后,我們發現,新插入的表記錄中,沒有賦值的字段仍然不是mysql的默認值,而是null值。 

    所以,按照上面所謂的通用insert語句,是無法讓未賦值字段的值變為mysql默認值的。這種insert語句無法做到通用。具體解決方案

 

上一篇簡單介紹了一個mysql的問題:字段默認值在使用全字段insert的時候,可能並不會生效。在使用mybatis時,雖然需要自己寫sql,但相比原始jdbc的方式來說,有一個很好的優勢——動態sql。針對前一篇文章提出的問題,mybatis的動態sql可以很好地解決這個問題。

1.問題分析

    上一篇文章中描述的問題,是由於我們誤將一個包含所有字段的insert語句做為通用的insert。那么顯而易見,解決此問題的方法是,我們需要針對不同的業務需求,嚴格按照需要插入的字段來寫不同的sql,不需要插入的字段,在insert語句中不能夠出現。舉例上一篇的blog表例子說明,假如我們有一個插入操作,只需要在插入時給author賦值,那么sql可以這么寫:

 

Xml代碼   收藏代碼
  1. <insert id="addOneBlog" parameterType="main.Blog">  
  2.     insert into blog(author)  
  3.     values (#{author})  
  4. </insert>  

 

 

    這個方法雖然奏效,但在實際項目開發中,為了開發效率的需要,我們仍然希望能夠有一個通用的insert語句,供所有涉及單表插入操作的業務調用。剛才說過,mybatis有一個非常強大的特色功能:動態sql,使用動態sql即可解決此問題。

2.<sql>、<include>、<trim>標簽簡介

    mybatis的動態sql功能包含了很多實用的標簽:<sql>標簽表示一個sql片段,使用此標簽不僅可以重用很多sql代碼,而且使sql語句更清晰;定義好<sql>標簽后,在調用它的地方使用<include>標簽,即可將定義好的sql片段拼接進來;<trim>標簽可以在標簽體內的sql片段首尾任意添加或覆蓋字符。

3.問題解決

先上代碼:

 

Xml代碼   收藏代碼
  1. <sql id="blogColumns">  
  2.     <trim suffixOverrides=",">  
  3.         <if test="title != null">title,</if>  
  4.         <if test="author != null">author,</if>  
  5.         <if test="content != null">content</if>  
  6.     </trim>  
  7. </sql>  
  8.   
  9. <sql id="blogValues">  
  10.     <trim suffixOverrides=",">  
  11.         <if test="title != null">#{title},</if>  
  12.         <if test="author != null">#{author},</if>  
  13.         <if test="content != null">#{content}</if>  
  14.     </trim>  
  15. </sql>  
  16.   
  17. <insert id="addOneBlog" parameterType="Blog">  
  18.     insert into blog(<include refid="blogColumns"/>)  
  19.     values (<include refid="blogValues"/>)  
  20. </insert>  

     對於blog表,上面這段代碼即可實現我們想要的insert重用,不管插入的字段有多少,我們都可以使用它來實現所有單表insert操作。上面代碼中,先定義兩個sql片段,分別代表insert語句中的字段列表和參數列表,並使用<trim>標簽去除片段首尾可能出現的多余的“,”字符。最后寫一個簡單的insert,並將上面的sql片段拼接進來。

4.結尾

    關於mybatis的動態sql,它有很多強大的,可高度重用sql的功能。大家如果對一些標簽的作用不太清楚,請期待我后續的博文。作為一個半自動的持久層框架,我們雖然需要自己寫sql語句,但mybatis的動態sql能夠最大限度地減少我們的代碼量,這也是在ORM橫行的JavaEE世界里,mybatis能夠獨樹一幟的原因。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM