Mybatis-常見(jiàn)SQL語(yǔ)句示例

官方說(shuō)明文檔:http://www.mybatis.org/mybatis-3/zh/index.html#

resultType和resultMap區(qū)別

resultType:從這條語(yǔ)句中返回的期望類(lèi)型的類(lèi)的完全限定名或別名。注意如果是集合情形,那應(yīng)該是集合可以包含的類(lèi)型,而不能是集合本身。使用 resultType 或 resultMap,但不能同時(shí)使用。

也就是說(shuō),使用resultType直接表示的就是返回類(lèi)型,可以是基本類(lèi)型(int、string)、list、map這些,也可以是具體的pojo對(duì)象

  • 完全限定名,意思是例如返回Task對(duì)象,那么值填寫(xiě)的是該Task類(lèi)的完整類(lèi)路徑;如果返回的是基礎(chǔ)類(lèi)型,就是類(lèi)似java.util.Map
  • 別名,意思是例如返回map類(lèi)型,我們不需要寫(xiě)完整的java.util.Map,可以用map替代
  • 不能是集合本身,這句話意思是例如接口需要返回List<Task>,那么直接寫(xiě)resultType="com.baidu.vo.Task",而不是寫(xiě)成resultType="List<com.baidu.vo.Task>"

resultMap:外部 resultMap 的命名引用。結(jié)果集的映射是 MyBatis 最強(qiáng)大的特性,對(duì)其有一個(gè)很好的理解的話,許多復(fù)雜映射的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同時(shí)使用。

相對(duì)復(fù)雜一點(diǎn),需要先定義一個(gè)外部標(biāo)簽<resultMap>,這里面一般定義了結(jié)果到pojo的映射關(guān)系,有id屬性,在具體的查詢(xún)語(yǔ)句中通過(guò)id尋找對(duì)應(yīng)的resultMap

  • 外部 resultMap 的命名引用,意思是并不是直接的返回類(lèi)型,只是一個(gè)引用標(biāo)識(shí),需要去找對(duì)應(yīng)的該引用的定義地方

DEMO-resultType

  • select * from task where id = {id} 輸出單個(gè)Task對(duì)象

TaskMapper.xml代碼

<select id="select" parameterType="int" resultType="com.baidu.pojo.entity.Task">
        select * from task where id = #{id}
</select>

TaskMapper.java代碼

Task select(int id);
  • select * from task 輸出Task集合

TaskMapper.xml代碼

<select id="select" resultType="com.baidu.pojo.entity.Task">
        select * from task 
</select>

TaskMapper.java代碼

List<Task> select();

note:通過(guò)上面兩個(gè)例子發(fā)現(xiàn),無(wú)論輸出單個(gè)對(duì)象還是一個(gè)列表,resultType的類(lèi)型都是一樣的。如果第二個(gè)例子中,TaskMapper.java里面方法返回值類(lèi)型是Task而不是List<Task>的話,當(dāng)查詢(xún)的結(jié)果包含多條語(yǔ)句時(shí),就會(huì)拋TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 10

  • select count(*) from task

TaskMapper.xml代碼

<select id="select" resultType="int">
        select count(*) from task
</select>

TaskMapper.java代碼

int select();
  • select name from task where id = {id} 輸出單個(gè)name

TaskMapper.xml代碼

<select id="select" parameterType="int" resultType="String">
        select name from task where id = #{id}
</select>

TaskMapper.java代碼

String select(int id);
  • select distinct name from task 輸出name集合

TaskMapper.xml代碼

<select id="select" resultType="String">
        select distinct name from task
</select>

TaskMapper.java代碼

List<String> select();

note:無(wú)論是單個(gè)name還是一個(gè)name集合,resultType都是String

  • select id, name from task where id = {id}

TaskMapper.xml代碼

<select id="select" resultType="map">
        select id, name from task where id = #{id}
</select>

TaskMapper.java代碼

Map select();

note:返回類(lèi)型是map時(shí),一條記錄會(huì)映射為一個(gè)map對(duì)象,列名對(duì)應(yīng)鍵,結(jié)果對(duì)應(yīng)值,如果是多條結(jié)果,那么應(yīng)該映射為類(lèi)型的map的一個(gè)集合

  • select status, count(*) as num from task group by status desc 統(tǒng)計(jì)任務(wù)表里所有狀態(tài)的個(gè)數(shù)

TaskMapper.xml代碼

<select id="select" resultType="hashmap">
        select status, count(*) as num from task group by status desc
</select>

TaskMapper.java代碼

List<HashMap> select();

note:注意這里的返回值是一個(gè)list,list中的元素是map對(duì)象,假如group之后有4組,那么就是包含4個(gè)map的數(shù)組

  • select * from task where id in (3, 4, 5) 參數(shù)是一個(gè)數(shù)組

TaskMapper.xml代碼

<select id="select" resultType="com.baidu.pojo.entity.Task">
        select * from task where id in
        <foreach item="item" index="index" collection="list"
                 open="(" separator="," close=")">
            #{item}
        </foreach>
</select>

TaskMapper.java代碼

List<Task> select(List ids);

note:item代表循環(huán)中的具體對(duì)象,如果collection屬性是list,那item就表示list中的一個(gè)元素;collection是遍歷的對(duì)象,可以是list、array,如果Mapper.java里傳入?yún)?shù)時(shí)使用@param(“param”)來(lái)設(shè)置名字,那這里的collection屬性就填寫(xiě)對(duì)應(yīng)的參數(shù)名;separator是分隔符,例如sql中出現(xiàn)in語(yǔ)句時(shí),就會(huì)設(shè)置separator=“,”分隔;open和close代表in語(yǔ)句里面的前后括號(hào)

  • insert into task (title, name) values ('標(biāo)題', '名字') 參數(shù)是一個(gè)map

TaskMapper.xml代碼

<insert id="insert" parameterType="map">
        insert into task
        <foreach collection="map.keys" item="key" open="(" close=")" separator=",">
            ${key}
        </foreach>
        values
        <foreach collection="map.keys" item="key" open="(" close=")" separator=",">
            #{map[${key}]}
        </foreach>
</insert>

TaskMapper.java代碼

int test(@Param("map") Map map);

note:這里Mapper.java文件里面使用的@param注解,對(duì)應(yīng)的collection就使用注解定義好的名字

DEMO-resultMap

定義一個(gè)Task類(lèi)

public class Task {
    private Integer id;
    private String title;
    private String name;
    private Date createAt;

    public Integer getId() {return id;}
    public void setId(Integer id) {this.id = id;}
    public String getTitle() {return title;}
    public void setTitle(String title) {this.title = title;}
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public Date getCreateAt() {return createAt;}
    public void setCreateAt(Date createAt) {this.createAt = createAt;}
}

定義一個(gè)resultMap

<resultMap id="BaseResultMap" type="com.baidu.pojo.entity.Task">
        <id column="id" property="id" jdbcType="INTEGER"/>
        <result column="title" property="title" jdbcType="VARCHAR"/>
        <result column="name" property="name" jdbcType="VARCHAR"/>
        <result column="create_at" property="createAt" jdbcType="TIMESTAMP"/>
</resultMap>

note:column代表數(shù)據(jù)庫(kù)表里面的屬性,property代表賦值給實(shí)體對(duì)象的屬性

定義一個(gè)sql

<sql id="Base_Column_List">
        id, title, name, create_at
</sql>

note:這個(gè)元素是用來(lái)定義可以重復(fù)使用的sql代碼語(yǔ)句的,這里面把Task表的全部列名定義為了一個(gè)sql,是為了下面查詢(xún)語(yǔ)句的重復(fù)使用

  • select * from task where create_at = '2017-07-07' 查詢(xún)數(shù)據(jù)

TaskMapper.xml代碼

<select id="select" resultMap="BaseResultMap" parameterType="com.baidu.pojo.entity.Task">
        select <include refid="Base_Column_List"/> from task
        <where>
            <if test="id != null">id=#{id}</if>
            <if test="title != null">and title=#{title}</if>
            <if test="name != null">and name=#{name}</if>
            <if test="createAt != null">and create_at=#{createAt}</if>
        </where>
</select>

TaskMapper.java代碼

List<Task> select(Task task);

note:這里用到了resultMap屬性,where元素知道只有在一個(gè)以上的if條件有值的情況下才去插入WHERE子句。而且,若最后的內(nèi)容是AND或OR開(kāi)頭的,where元素也知道如何將他們?nèi)コ_@里面的if語(yǔ)句很直觀,就是代表如果傳入的參數(shù)中,該屬性不為空,那么就把該條件帶上去

  • insert into task (title, name,create_at) values ('標(biāo)題', '名字', '2017-07-07') 插入數(shù)據(jù)

TaskMapper.xml代碼

<insert id="add" parameterType="com.baidu.pojo.entity.Task" useGeneratedKeys="true" keyProperty="id">
        insert into task (<include refid="Base_Column_List"/>) values (
        #{id,jdbcType=INTEGER}, 
        #{title,jdbcType=VARCHAR},
        #{name,jdbcType=VARCHAR},
        #{createAt,jdbcType=TIMESTAMP} )
</insert>

TaskMapper.java代碼

int add(Task task);

note:useGeneratedKeys表示是否使用JDBC的getGenereatedKeys方法獲取主鍵并賦值到keyProperty設(shè)置的屬性中,這里就是id是自增長(zhǎng)的主鍵,值可以通過(guò)getGenereatedKeys方法獲取然后復(fù)制到task對(duì)象的屬性上面

  • update task set name = '名字' where id = {id} 更新數(shù)據(jù)

TaskMapper.xml代碼

<update id="update" parameterType="com.baidu.pojo.entity.Task">
        update task
        <set>
            <if test="title != null">title=#{title,jdbcType=VARCHAR},</if>
            <if test="name != null">name=#{name,jdbcType= VARCHAR},</if>
            <if test="createAt != null">create_at=#{createAt,jdbcType=TIMESTAMP}</if>
        </set>
</update>

TaskMapper.java代碼

int update(Task task);

note:set 元素會(huì)動(dòng)態(tài)前置SET關(guān)鍵字,同時(shí)也會(huì)消除無(wú)關(guān)的逗號(hào)

  • delete from task where create_at = '2017-07-07' 刪除數(shù)據(jù)

TaskMapper.xml代碼

<delete id="select" parameterType="com.baidu.pojo.entity.Task">
        delete from task
        <where>
            <if test="id != null">id=#{id}</if>
            <if test="title != null">and title=#{title}</if>
            <if test="name != null">and name=#{name}</if>
            <if test="createAt != null">and create_at=#{createAt}</if>
        </where>
</delete>

TaskMapper.java代碼

int delete(Task task);
  • select * from task where title = {title} and name = {name} 利用索引傳遞多個(gè)參數(shù)

TaskMapper.xml代碼

<select id="select" resultMap="baseResultMap">
        select <include refid="Base_Column_List"/> from task where title = #{0} and name = #{1}
</select>

TaskMapper.java代碼

List<Task> select(String title, String name);

note:使用#{index}指定參數(shù),索引從0開(kāi)始

  • select * from task where title = {title} and name = {name} 利用@param注解傳遞多個(gè)參數(shù)

TaskMapper.xml代碼

<select id="select" resultMap="baseResultMap">
        select <include refid="Base_Column_List"/> from task where title = #{title} and name = #{name}
   
</select>

TaskMapper.java代碼

List<Task> select(@Param("title") String title, @Param("name") String name);

DEMO-關(guān)聯(lián)查詢(xún)

描述:一個(gè)計(jì)劃有一個(gè)執(zhí)行人,一個(gè)人只能執(zhí)行一個(gè)計(jì)劃

定義一個(gè)User類(lèi)

public class User {
    private Integer id;
    private String name;
    
    public Integer getId() {return id;}
    public void setId(Integer id) {this.id = id;}
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
}

定義一個(gè)Plan類(lèi)

public class Plan {
    private Integer id;
    private String name;
    private User user;

    public Integer getId() {return id;}
    public void setId(Integer id) {this.id = id;}
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public String getUser() {return user;}
    public void setUser(User user) {this. user = user;}
}
  • select * from plan, user where plan.uid = user.id and plan.id = #{id} 一對(duì)一關(guān)聯(lián)查詢(xún)(方式一)

定義一個(gè)resultMap

<resultMap id="PlanUserMap" type="com.baidu.pojo.entity.Plan">
        <id column="id" property="id" jdbcType="INTEGER"/>
        <result column="name" property="name" jdbcType="VARCHAR"/>
        <association property="user" javaType="com.baidu.pojo.entity.User">
            <id column="id" property="id" jdbcType="INTEGER"/>
            <result column="name" property="name" jdbcType="VARCHAR"/>
        </association>
</resultMap>

PlanMapper.xml代碼

<select id="select" parameterType="int" resultMap="PlanUserMap">
        select * from plan, user where plan.uid = user.id and plan.id = #{id}       
</select>

PlanMapper.java代碼

Plan select(int id);

note:uid是Task表的外鍵,這里面用的是association標(biāo)簽

  • select * from plan, user where plan.uid = user.id and plan.id = #{id} 一對(duì)一關(guān)聯(lián)查詢(xún)(方式二)

定義一個(gè)resultMap

<resultMap id="PlanUserMap" type="com.baidu.pojo.entity.Plan">
        <id column="id" property="id" jdbcType="INTEGER"/>
        <result column="name" property="name" jdbcType="VARCHAR"/>
        <association column="uid" property="user" select="getUser"/>
</resultMap>

PlanMapper.xml代碼

<select id="select" parameterType="int" resultMap="PlanUserMap">
        select * from plan where id = #{id}       
</select>

<select id="getUser" parameterType="int" resultType="com.baidu.pojo.entity.User">
        select * from user where id = #{id}       
</select>

PlanMapper.java代碼

Plan select(int id);

note:先查詢(xún)出一條Plan記錄,然后把該記錄的uid值作為User表的id,查詢(xún)對(duì)應(yīng)的User記錄


描述:一個(gè)計(jì)劃可以執(zhí)行多個(gè)任務(wù),一個(gè)任務(wù)屬于一個(gè)計(jì)劃

定義一個(gè)Task類(lèi)

public class Task {
    private Integer id;
    private String title;
    private String name;
    private Date createAt;

    public Integer getId() {return id;}
    public void setId(Integer id) {this.id = id;}
    public String getTitle() {return title;}
    public void setTitle(String title) {this.title = title;}
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public Date getCreateAt() {return createAt;}
    public void setCreateAt(Date createAt) {this.createAt = createAt;}
}

定義一個(gè)Plan類(lèi)

public class Plan {
    private Integer id;
    private String name;
    private List<Task> tasks;

    public Integer getId() {return id;}
    public void setId(Integer id) {this.id = id;}
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public List<Task> getTasks() {return tasks;}
    public void setTasks(List<Task> tasks) {this. tasks = tasks;}
}
  • select * from plan, task where plan.id = task.pid and plan.id = #{id} 一對(duì)多關(guān)聯(lián)查詢(xún)(方式一)

定義一個(gè)resultMap

<resultMap id="PlanTaskMap" type="com.baidu.pojo.entity.Plan">
        <id column="id" property="id" jdbcType="INTEGER"/>
        <result column="name" property="name" jdbcType="VARCHAR"/>
        <collection property="tasks" ofType="com.baidu.pojo.entity.Task">
             <id column="id" property="id" jdbcType="INTEGER"/>
             <result column="title" property="title" jdbcType="VARCHAR"/>
             <result column="name" property="name" jdbcType="VARCHAR"/>
             <result column="create_at" property="createAt" jdbcType="TIMASTAMP"/>
        </collection>
</resultMap>

PlanMapper.xml代碼

<select id="select" parameterType="int" resultMap="PlanTaskMap">
        select * from plan, task where plan.id = task.pid and plan.id = #{id}       
</select>

PlanMapper.java代碼

Plan select(int id);

note:pid是Task表的外鍵,這里面用的是collection標(biāo)簽

  • select * from plan, task where plan.id = task.pid and plan.id = #{id} 一對(duì)多關(guān)聯(lián)查詢(xún)(方式二)

定義一個(gè)resultMap

<resultMap id="PlanTaskMap" type="com.baidu.pojo.entity.Plan">
        <id column="id" property="id" jdbcType="INTEGER"/>
        <result column="name" property="name" jdbcType="VARCHAR"/>
        <collection column="pid" property="tasks" ofType="com.baidu.pojo.entity.Task" select="getTask">
        </collection>
</resultMap>

PlanMapper.xml代碼

<select id="select" parameterType="int" resultMap="PlanTaskMap">
        select * from plan where id = #{id}       
</select>

<select id="getTask" parameterType="int" resultType="com.baidu.pojo.entity.Task">
        select * from task where id = #{id}       
</select>

PlanMapper.java代碼

Plan select(int id);

note:先查詢(xún)出一條Plan記錄,然后把該記錄的id值作為T(mén)ask表的pid,查詢(xún)對(duì)應(yīng)的多條Task記錄

補(bǔ)充

我們發(fā)現(xiàn),無(wú)論結(jié)果是返回一個(gè)值還是一個(gè)數(shù)組,resultType的返回類(lèi)型都是單一的對(duì)象,但是Mapper.java里面有的是單一值,有的是list,MyBatis是如何知道我們想要的是一個(gè)結(jié)果還是多個(gè)結(jié)果。其實(shí),無(wú)論返回一個(gè)還是多個(gè),MyBatis都是按照多個(gè)結(jié)果查詢(xún),看一下selectOne源碼:

public <T> T selectOne(String statement, Object parameter) {
    List<T> list = this.<T>selectList(statement, parameter);
    if (list.size() == 1) {
        return list.get(0);
    } else if (list.size() > 1) {
        throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
    } else {
        return null;
    }
}

即使使用的是selectOne方法,里面調(diào)用的還是selectList方法,然后返回第一個(gè)值,代碼中有一句大家可能會(huì)很熟悉。當(dāng)返回值有多個(gè),但是接口中的返回類(lèi)型是單一的對(duì)象的時(shí)候,就會(huì)拋該錯(cuò)誤

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,208評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 175,746評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,666評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,477評(píng)論 6 407
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 54,960評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,200評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,726評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,617評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,807評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,049評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,425評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,674評(píng)論 1 281
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,432評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,769評(píng)論 2 372

推薦閱讀更多精彩內(nèi)容