使用Mybatis實現動態SQL(一)


使用Mybatis實現動態SQL

作者 : Stanley 羅昊

轉載請注明出處和署名,謝謝!

寫在前面:

       *本章節適合有Mybatis基礎者觀看*

前置說明

我現在寫一個查詢全部的sql語句,這個對各位來說,想必應該是非常簡單,我舉個例子:

select * from studnet //查詢全部

我現在需求又變了。我現在要根據年齡進行查詢了,那是不是也依然很簡單:

select * from student where age = #{age} //根據年齡查詢學生

那么,我現在再來一個需求,根據年齡跟姓名來查:

select * from student where age = #{age} and name=#{name};

但是,我們仔細發現,我剛才在寫sql語句,就需要復制粘貼,那也就意味着,在這以上的sql語句是重復的,也就是說三個語句里,查詢的都是同一張表,只不過加了一些條件;

因此,我沒有必要寫三次,其實我們寫一次就夠了

如果使用動態sql來實現的話,就非常方便,比如:

                                我第一次使用的時候,僅使用select * from student 僅僅的查詢全部,用於初始化

                                我第二次再去使用的時候 僅使用 where = age

                                我第三次再去使用的時候 就成了 where = age and name =name

可以靈活的控制sql語句,這就是動態sql;

可以設想一下,如果沒有動態sql,我們是不是一個功能模塊,就要寫三段sql語句,很顯然讓代碼變的非常臃腫不整潔,效率還低,所以,在正常的企業開發當中,動態sql用點居多!

動態SQL

那么,到底怎么實現呢?這個,就用到了mybatis xml文件中的動態標簽了;

首先,我們需要看一下查詢條件:本次業務涉及到查詢所有、根據學生年齡查詢、根據學生年齡並且根據學生姓名進行查詢;

查詢所有,因為要在頁面初始化中使用,所以頁面加載之后需要展示出來,另外那些條件,就是幾個篩選條件,可以利用他們滿足自己的查詢需要;

現在,我們就根據以上業務來完成一個動態sql;

在要進行查詢的xml文件中編寫:

<select id = "selectAllorbynameAndage" resultType = "Student">

select * from student where

<if test = " name!= null and name!= ' ' ">//如果傳過來的student對象有name屬性,並且該屬性不為空,便執行次條件

student = #{name}

</if>

<if test = "age !=null and age != ' ' ">

And student = #{age}

</if>

</select>

 

講解:

1.if:什么叫if,就是如果有這么怎辦,如果沒怎么怎么辦,在這里的意思就是,你現在查的時候,要是傳入了一個名字,那么,我就根據你傳過來的name進行查詢。

換句話說,如果你沒傳這個字段,那么是不是就不進入這個判斷了,也就代表你沒寫這個where一樣;

用意:我現在傳過來一個學生對象,如果這個學生對象包含了一個name屬性,且name屬性不為空,那么我就要把這個student = #{name}給加上

if后面的test里面就寫執行條件

2.我們現在除了name之外,是不是還有可能有age;

根據以上的業務,我們發現,也是有根據age進行查詢的,那么,我們僅需在下面跟上一個if里面來寫關於age的判決即可;

但是值得注意的是,本次編寫前面需要加上and;

and:為什么在加and呢?

我們可以設想一下,目前的sql語句是這樣的:

select * from student where name = #{name}

如果不加and的話,是不是就變成了:

 select * from student where name = #{name}age = #{age}

這樣顯然是不對的,sql語法都出錯兩,所以需要在前面加上and,加上and之后就是合法的sql語句了:

 select * from student where name = #{name}And age = #{age}

解決sql語句解釋失敗

那么,問題來了,以上寫的那種方案是,name 跟 age 必須全部存在,才可以生效,一旦不存在,那么就會報錯,我現在認定這個name時在時不在的情況;

我舉個例子,本次查詢,僅僅按照age查詢,這個時候,age傳過來了,但是name沒有傳過來,因為我只查詢age,肯定只用把age傳過來,這個時候,name拿不到值,就導致了這樣的sql語句:

select * from student where And age = #{age}

這就很明顯,sql語句怎么可能寫成這樣,這個and就非常令人厭煩,為什么會導致成這樣呢?

還記得我們寫的一個if標簽嗎?如果name = null and name = ‘ ’,我這條標簽就不去執行一旦不去執行就變成以上那樣了,原本有name是這樣的:

 select * from student where name = #{name}And age = #{age}

你現在name為空了,那就表明name  = #{name}就消失了

這個and你也去不掉它,你一旦去掉了,又會造成另外一種sql語法非法,如何解決這個不協調的字段呢?

兩種解決方案

第一種:

<select id = "selectAllorbynameAndage" resultType = "Student">

select * from student where 1 = 1

<if test = " name!= null and name!= ' ' ">//如果傳過來的student對象有name屬性,並且該屬性不為空,便執行次條件

And student = #{name}

</if>

<if test = "age !=null and age != ' ' ">

And student = #{age}

</if>

</select>

我把studnt = name前面也加了一個and,但是這樣做會導致本次sql語句不成立,沒關系,我在where后面加了一個 1 = 1,就代表永遠成立,也就是強制讓數據庫認下這個and;

第二種【最佳/推薦】:

<select id = "selectAllorbynameAndage" resultType = "Student">

select * from student

<where>

<if test = " name!= null and name!= ' ' ">//如果傳過來的student對象有name屬性,並且該屬性不為空,便執行次條件

And student = #{name}

</if>

<if test = "age !=null and age != ' ' ">

And student = #{age}

</if>

</where>

</select>

現在呢,我們直接用where標簽把sql包裹,把主查詢后面的where就刪掉,因為已經不需要了,那么加上這個where標簽后,sql變成什么樣子了呢?

 select * from student <where> and  name = #{name}and age = #{age}

這樣的sql語句看似是不是像是那種有問題的sql語句,因為在where后面就有and,但是沒關心,不用管,這個<where>標簽是智能的,它會自動處理第一個and,不會處理第二個;

什么意思呢?就是本次查詢,如果你需要這個and,那么我就給你加上,如果你不需要這個and,我就不給你加,很顯然,本次查詢不需要這個and,所以就沒給你加;

這個時候,你把第一個and給刪了,再去執行,你會發現跟沒刪一樣,如果你加上這個and,你就會發現,跟沒加一樣,就是這么智能,非常便捷;

但是,如果你把第二個或往后的and刪了,就會出問題了,因為它只會幫你處理第第一個and;

所以,原理是這樣的:

剛才我說了,如果沒有name,那么第一個if就會消失,緊接着,age是不是就頂替name了,那么age就是第一個了

<select id = "selectAllorbynameAndage" resultType = "Student">

select * from student

<where>

<if test = "age !=null and age != ' ' ">

And student = #{age}

</if>

</where>

</select>

那么這個智能where標簽恰到好處的把第一個and給消掉了,從而完成了根據age查詢;

了解以上概念后,我們就把上面的業務給全部寫完吧,如果age跟name均不為空,那么我就根據這兩個進行查詢;

<select id = "selectAllorbynameAndage" resultType = "Student">

select * from student

<where>

<if test = " name!= null and name!= ' ' ">//如果傳過來的student對象有name屬性,並且該屬性不為空,便執行次條件

And student = #{name}

</if>

<if test = "age !=null and age != ' ' ">

And student = #{age}

</if>

<if test = "age ! = null and age !=' ' And name !=null and name ! = ' ' ">

And student = #{name} And student = #{age}

</if>

</where>

</select>

 


免責聲明!

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



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