在項目中使用mybatis作爲持久層框架,mysql數據庫。項目上線前,DBA要求咱們將每張數據庫表中的字段都設置默認值和not null。以前項目中有一些insert語句是將表中全部字段都列出來,而後把它作爲一個通用的插入語句來使用。舉個簡單的例子:假如一張數據庫表blog中有以下幾個字段:id,title,content,author,除id外,每一個字段都設置了默認值Empty String(空字符串),寫的一個insert語句是這樣的:
mysql
- <insert id="addOneBlog" parameterType="main.Blog">
- insert into blog(title,author,content)
- values(#{title},#{author},#{content})
- </insert>
原覺得有這麼一個insert語句就萬事大吉了,咱們覺得,之後作插入操做的時候,不管有多少個字段,都使用這一個insert語句,若是字段沒有值,就會被賦值爲mysql字段的默認值。。。
但事實證實,根本不是這樣的。
當咱們只給title字段賦值,而後執行一個insert語句時,mybatis立刻報出這樣的異常:
sql
- 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能夠很好地解決這個問題。mybatis
1.問題分析框架
上一篇文章中描述的問題,是因爲咱們誤將一個包含全部字段的insert語句作爲通用的insert。那麼顯而易見,解決此問題的方法是,咱們須要針對不一樣的業務需求,嚴格按照須要插入的字段來寫不一樣的sql,不須要插入的字段,在insert語句中不可以出現。舉例上一篇的blog表例子說明,假如咱們有一個插入操做,只須要在插入時給author賦值,那麼sql能夠這麼寫:ide
- <insert id="addOneBlog" parameterType="main.Blog">
- insert into blog(author)
- values (#{author})
- </insert>
這個方法雖然奏效,但在實際項目開發中,爲了開發效率的須要,咱們仍然但願可以有一個通用的insert語句,供全部涉及單表插入操做的業務調用。剛纔說過,mybatis有一個很是強大的特點功能:動態sql,使用動態sql便可解決此問題。spa
2.<sql>、<include>、<trim>標籤簡介blog
mybatis的動態sql功能包含了不少實用的標籤:<sql>標籤表示一個sql片斷,使用此標籤不只能夠重用不少sql代碼,並且使sql語句更清晰;定義好<sql>標籤後,在調用它的地方使用<include>標籤,便可將定義好的sql片斷拼接進來;<trim>標籤能夠在標籤體內的sql片斷首尾任意添加或覆蓋字符。開發
3.問題解決字符串
先上代碼:
- <sql id="blogColumns">
- <trim suffixOverrides=",">
- <if test="title != null">title,</if>
- <if test="author != null">author,</if>
- <if test="content != null">content</if>
- </trim>
- </sql>
- <sql id="blogValues">
- <trim suffixOverrides=",">
- <if test="title != null">#{title},</if>
- <if test="author != null">#{author},</if>
- <if test="content != null">#{content}</if>
- </trim>
- </sql>
- <insert id="addOneBlog" parameterType="Blog">
- insert into blog(<include refid="blogColumns"/>)
- values (<include refid="blogValues"/>)
- </insert>
對於blog表,上面這段代碼便可實現咱們想要的insert重用,無論插入的字段有多少,咱們均可以使用它來實現全部單表insert操做。上面代碼中,先定義兩個sql片斷,分別表明insert語句中的字段列表和參數列表,並使用<trim>標籤去除片斷首尾可能出現的多餘的「,」字符。最後寫一個簡單的insert,並將上面的sql片斷拼接進來。
4.結尾
關於mybatis的動態sql,它有不少強大的,可高度重用sql的功能。你們若是對一些標籤的做用不太清楚,請期待我後續的博文。做爲一個半自動的持久層框架,咱們雖然須要本身寫sql語句,但mybatis的動態sql可以最大限度地減小咱們的代碼量,這也是在ORM橫行的JavaEE世界裏,mybatis可以獨樹一幟的緣由。