Mybatis(二)

parameterType(輸入類型)

傳遞簡單類型

使用#{}占位符,或者${}進(jìn)行sql拼接

傳遞pojo對象

Mybatis使用ognl表達(dá)式解析對象字段的值,#{}或者${}括號(hào)中的值為pojo屬性名稱

傳遞pojo包裝對象

開發(fā)中通過可以使用pojo傳遞查詢條件

查詢條件可能是綜合的查詢條件,不僅包括用戶查詢條件還包括其它的查詢條件(比如查詢用戶信息的時(shí)候,將用戶購買商品信息也作為查詢條件),這時(shí)可以使用包裝對象傳遞輸入?yún)?shù)

包裝對象:Pojo類中的一個(gè)屬性是另外一個(gè)pojo

需求:根據(jù)用戶名模糊查詢用戶信息,查詢條件放到QueryVo的user屬性中

  • 編寫QueryVo
package com.cuzz.pojo;

public class QueryVo {

    // 包含其他pojo
    
    public User user;
    
    public User getUser() {
        return user;
    }
    
    public void setUser(User user) {
        this.user = user;
    }
}
  • sql語句
    SELECT * FROM user WHERE username LIKE '%張%'
  • Mapper.xml文件
    <!-- 根據(jù)用戶的名模糊查詢 -->
    <select id="queryUserByQueryVo" parameterType="QueryVo" resultType="com.cuzz.pojo.User">
    SELECT * FROM `user` WHERE username LIKE "%"#{user.username}"%"
    </select>
  • Mapper接口
    在UserMapper接口中添加方法
    // 根據(jù)包裝類查詢用戶
    List<User> queryUserByQueryVo(QueryVo queryVo);
  • 測試方法
@Test
public void testQueryUserByQueryVo() {
    // mybatis和spring整合,整合之后,交給spring管理
    SqlSession sqlSession = this.sqlSessionFactory.openSession();
    // 創(chuàng)建Mapper接口的動(dòng)態(tài)代理對象,整合之后,交給spring管理
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    // 使用userMapper執(zhí)行查詢,使用包裝對象
    QueryVo queryVo = new QueryVo();
    // 設(shè)置user條件
    User user = new User();
    user.setUsername("張");
    // 設(shè)置到包裝對象中
    queryVo.setUser(user);

    // 執(zhí)行查詢
    List<User> list = userMapper.queryUserByQueryVo(queryVo);
    for (User u : list) {
        System.out.println(u);
    }

    // mybatis和spring整合,整合之后,交給spring管理
    sqlSession.close();
}

resultType(輸出類型)

輸出簡單類型

  • 需求:查詢用戶表數(shù)據(jù)條數(shù)
  • Sql
    SELECT count(*) FROM `user`
  • Mapper.xml文件
    <!-- 查詢用戶的條數(shù) -->
    <select id="queryUserCount" resultType="int">
        SELECT count(*) FROM `user`
    </select>
  • Mapper接口
    int queryUserCount();

輸出pojo對象

輸出pojo列表

resultMap(輸出類型)

resultType可以指定將查詢結(jié)果映射為pojo,但需要pojo的屬性名和sql查詢的列名一致方可映射成功。

如果sql查詢字段名和pojo的屬性名不一致,可以通過resultMap將字段名和屬性名作一個(gè)對應(yīng)關(guān)系 ,resultMap實(shí)質(zhì)上還需要將查詢結(jié)果映射到pojo對象中。

resultMap可以實(shí)現(xiàn)將查詢結(jié)果映射為復(fù)雜類型的pojo,比如在查詢結(jié)果映射對象中包括pojo和list實(shí)現(xiàn)一對一查詢和一對多查詢。

  • 需求:查詢訂單表order的所有數(shù)據(jù)
  • Sql
    SELECT id, user_id, number, createtime, note FROM `order`
  • 數(shù)據(jù)表


    image.png
  • order對象
public class Order {
    // 訂單id
    private int id;
    // 用戶id
    private Integer userId;
    // 訂單號(hào)
    private String number;
    // 訂單創(chuàng)建時(shí)間
    private Date createtime;
    // 備注
    private String note;
}
  • Mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace:命名空間,用于隔離sql,還有一個(gè)很重要的作用,Mapper動(dòng)態(tài)代理開發(fā)的時(shí)候使用,需要指定Mapper的類路徑 -->
<mapper namespace="com.cuzz.mapper.OrderMapper">
    <!-- 查詢所有的訂單數(shù)據(jù) -->
    <select id="queryOrderAll" resultType="order">
        SELECT id, user_id,
        number,
        createtime, note FROM `order`
    </select>
</mapper>
  • Mapper接口
public interface OrderMapper {
    
    //  查詢所有訂單
    List<Order> queryOrderAll();
}
  • 發(fā)現(xiàn)userId為null
  • 使用resultMap
    由于上邊的mapper.xml中sql查詢列(user_id)和Order類屬性(userId)不一致,所以查詢結(jié)果不能映射到pojo中。
    需要定義resultMap,把orderResultMap將sql查詢列(user_id)和Order類屬性(userId)對應(yīng)起來
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace:命名空間,用于隔離sql,還有一個(gè)很重要的作用,Mapper動(dòng)態(tài)代理開發(fā)的時(shí)候使用,需要指定Mapper的類路徑 -->
<mapper namespace="com.cuzz.mapper.OrderMapper">

    <!-- resultMap最終還是要將結(jié)果映射到pojo上,type就是指定映射到哪一個(gè)pojo -->
    <!-- id:設(shè)置ResultMap的id -->
    <resultMap type="order" id="orderResultMap">
        <!-- 定義主鍵 ,非常重要。如果是多個(gè)字段,則定義多個(gè)id -->
        <!-- property:主鍵在pojo中的屬性名 -->
        <!-- column:主鍵在數(shù)據(jù)庫中的列名 -->
        <id property="id" column="id" />

        <!-- 定義普通屬性 -->
        <result property="userId" column="user_id" />
        <result property="number" column="number" />
        <result property="createtime" column="createtime" />
        <result property="note" column="note" />
    </resultMap>

    <!-- 查詢所有的訂單數(shù)據(jù) -->
    <select id="queryOrderAll" resultMap="orderResultMap">
        SELECT id, user_id,
        number,
        createtime, note FROM `order`
    </select>

</mapper>

動(dòng)態(tài)SQL

通過mybatis提供的各種標(biāo)簽方法實(shí)現(xiàn)動(dòng)態(tài)拼接sql。

if 標(biāo)簽

  • 需求:根據(jù)性別和名字查詢用戶
  • 查詢sql:
    SELECT id, username, birthday, sex, address FROM `user` WHERE sex = 1 AND username LIKE '%張%'
  • Mapper.xml
<!-- 根據(jù)條件查詢用戶 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
    SELECT id, username, birthday, sex, address FROM `user`
    WHERE sex = #{sex} AND username LIKE
    '%${username}%'
</select>
  • Mapper接口
    List<User> queryUserByWhere(User user);
  • 這樣很不合理,查詢條件越多我們就編寫越多的sql
  • 使用if標(biāo)簽
    修改Mapper.xml文件
<!-- 根據(jù)條件查詢用戶 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
    SELECT id, username, birthday, sex, address FROM `user`
    WHERE 1=1
    <if test="sex != null and sex != ''">
        AND sex = #{sex}
    </if>
    <if test="username != null and username != ''">
        AND username LIKE
        '%${username}%'
    </if>
</select>

注意字符串類型的數(shù)據(jù)需要要做不等于空字符串校驗(yàn)。

where標(biāo)簽

上面的sql還有where 1=1 這樣的語句,很麻煩
可以使用where標(biāo)簽進(jìn)行改造

  • 修改Mapper.xml
<!-- 根據(jù)條件查詢用戶 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
    SELECT id, username, birthday, sex, address FROM `user`
<!-- where標(biāo)簽可以自動(dòng)添加where,同時(shí)處理sql語句中第一個(gè)and關(guān)鍵字 -->
    <where>
        <if test="sex != null">
            AND sex = #{sex}
        </if>
        <if test="username != null and username != ''">
            AND username LIKE
            '%${username}%'
        </if>
    </where>
</select>

SQL片段

  • Sql中可將重復(fù)的sql提取出來,使用時(shí)用include引用即可,最終達(dá)到sql重用的目的。

= 把上面例子中的id, username, birthday, sex, address提取出來,作為sql片段,如下:

<!-- 根據(jù)條件查詢用戶 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
    <!-- SELECT id, username, birthday, sex, address FROM `user` -->
    <!-- 使用include標(biāo)簽加載sql片段;refid是sql片段id -->
    SELECT <include refid="userFields" /> FROM `user`
    <!-- where標(biāo)簽可以自動(dòng)添加where關(guān)鍵字,同時(shí)處理sql語句中第一個(gè)and關(guān)鍵字 -->
    <where>
        <if test="sex != null">
            AND sex = #{sex}
        </if>
        <if test="username != null and username != ''">
            AND username LIKE
            '%${username}%'
        </if>
    </where>
</select>

<!-- 聲明sql片段 -->
<sql id="userFields">
    id, username, birthday, sex, address
</sql>
  • 如果要使用別的Mapper.xml配置的sql片段,可以在refid前面加上對應(yīng)的Mapper.xml的namespace

foreach 標(biāo)簽

  • 向sql傳遞數(shù)組或List,mybatis使用foreach解析,如下:
  • 需求:根據(jù)多個(gè)id查詢用戶信息
  • 查詢Sql:
    SELECT * FROM user WHERE id IN (1,10,24)
  • 改造QueryVo
    在pojo中定義list屬性ids儲(chǔ)存多個(gè)用戶的id
public class QueryVo {

    // 包含其他pojo
    private User user;
    
    private List<Integer> ids;
    
    getter/setter
}
  • Mapper.xml
<!-- 根據(jù)ids查詢用戶 -->
<select id="queryUserByIds" parameterType="queryVo" resultType="user">
    SELECT * FROM `user`
    <where>
        <!-- foreach標(biāo)簽,進(jìn)行遍歷 -->
        <!-- collection:遍歷的集合,這里是QueryVo的ids屬性 -->
        <!-- item:遍歷的項(xiàng)目,可以隨便寫,,但是和后面的#{}里面要一致 -->
        <!-- open:在前面添加的sql片段 -->
        <!-- close:在結(jié)尾處添加的sql片段 -->
        <!-- separator:指定遍歷的元素之間使用的分隔符 -->
        <foreach collection="ids" item="item" open="id IN (" close=")"
            separator=",">
            #{item}
        </foreach>
    </where>
</select>

關(guān)聯(lián)查詢

商品訂單數(shù)據(jù)模型

  • 訂單表:order
    記錄了用戶創(chuàng)建的訂單
    創(chuàng)建用戶:user_id(外鍵)
    訂單號(hào)
    創(chuàng)建時(shí)間
    訂單狀態(tài)
  • 用戶表:user
    記錄了購買商品的用戶信息
    Id:唯一標(biāo)識(shí)一個(gè)用戶
  • 一對一:一個(gè)訂單只能由一個(gè)用戶創(chuàng)建
  • 一對多:一個(gè)用戶可以創(chuàng)建多個(gè)訂單

一對一查詢

  • 需求:查詢所有訂單信息,關(guān)聯(lián)查詢下單用戶信息。
  • 注意:因?yàn)橐粋€(gè)訂單信息只會(huì)是一個(gè)人下的訂單,所以從查詢訂單信息出發(fā)關(guān)聯(lián)查詢用戶信息為一對一查詢。如果從用戶信息出發(fā)查詢用戶下的訂單信息則為一對多查詢,因?yàn)橐粋€(gè)用戶可以下多個(gè)訂單。
  • Sql語句:
SELECT
    o.id,
    o.user_id userId,
    o.number,
    o.createtime,
    o.note,
    u.username,
    u.address
FROM
    `order` o
LEFT JOIN `user` u ON o.user_id = u.id

使用resultType

使用resultType,改造訂單pojo類,此pojo類中包括了訂單信息和用戶信息
這樣返回對象的時(shí)候,mybatis自動(dòng)把用戶信息也注入進(jìn)來了

  • 改造pojo類
    OrderUser類繼承Order類后OrderUser類包括了Order類的所有字段,只需要定義用戶的信息字段即可
package com.cuzz.pojo;

public class OrderUser extends Order{
    private String username;
    private String address;
}
  • Mapper.xml
在UserMapper.xml添加sql,如下
<!-- 查詢訂單,同時(shí)包含用戶數(shù)據(jù) -->
<select id="queryOrderUser" resultType="orderUser">
    SELECT
    o.id,
    o.user_id
    userId,
    o.number,
    o.createtime,
    o.note,
    u.username,
    u.address
    FROM
    `order` o
    LEFT JOIN `user` u ON o.user_id = u.id
</select>
  • Mapper接口
    List<OrderUser> queryOrderUser();
  • 小結(jié)
    定義專門的pojo類作為輸出類型,其中定義了sql查詢結(jié)果集所有的字段。此方法較為簡單,企業(yè)中使用普遍。

使用resultMap

  • 使用resultMap,定義專門的resultMap用于映射一對一查詢結(jié)果。
  • 改造pojo類
    在Order類中加入U(xiǎn)ser屬性,user屬性中用于存儲(chǔ)關(guān)聯(lián)查詢的用戶信息,因?yàn)橛唵侮P(guān)聯(lián)查詢用戶是一對一關(guān)系,所以這里使用單個(gè)User對象存儲(chǔ)關(guān)聯(lián)查詢的用戶信息
package com.cuzz.pojo;

public class Order {
     // 訂單
    private Integer id;
    // 用戶id
    private Integer userId;
    // 訂單號(hào)
    private String number;
    // 備注
    private String note;
    
    // 用戶
    private User user;

}
  • Mapper.xml
    這里resultMap指定orderUserResultMap,如下:
<resultMap type="order" id="orderUserResultMap">
    <id property="id" column="id" />
    <result property="userId" column="user_id" />
    <result property="number" column="number" />
    <result property="createtime" column="createtime" />
    <result property="note" column="note" />

    <!-- association :配置一對一屬性 -->
    <!-- property:order里面的User屬性名 -->
    <!-- javaType:屬性類型 -->
    <association property="user" javaType="user">
        <!-- id:聲明主鍵,表示user_id是關(guān)聯(lián)查詢對象的唯一標(biāo)識(shí)-->
        <id property="id" column="user_id" />
        <result property="username" column="username" />
        <result property="address" column="address" />
    </association>

</resultMap>

<!-- 一對一關(guān)聯(lián),查詢訂單,訂單內(nèi)部包含用戶屬性 -->
<select id="queryOrderUserResultMap" resultMap="orderUserResultMap">
    SELECT
    o.id,
    o.user_id,
    o.number,
    o.createtime,
    o.note,
    u.username,
    u.address
    FROM
    `order` o
    LEFT JOIN `user` u ON o.user_id = u.id
</select>

一對多查詢

  • 案例:查詢所有用戶信息及用戶關(guān)聯(lián)的訂單信息。
    用戶信息和訂單信息為一對多關(guān)系。
  • Sql語句:
SELECT
    u.id,
    u.username,
    u.birthday,
    u.sex,
    u.address,
    o.id oid,
    o.number,
    o.createtime,
    o.note
FROM
    `user` u
LEFT JOIN `order` o ON u.id = o.user_id
  • 修改pojo類
    在User類中加入List<Order> orders屬性,如下圖:
public class User {
    private int id;
    private String username;
    private String sex;
    private Date birthday;
    private String address;
    private List<Order> orders;
}
  • Mapper.xml
<resultMap type="user" id="userOrderResultMap">
    <id property="id" column="id" />
    <result property="username" column="username" />
    <result property="birthday" column="birthday" />
    <result property="sex" column="sex" />
    <result property="address" column="address" />

    <!-- 配置一對多的關(guān)系 -->
    <collection property="orders" javaType="list" ofType="order">
        <!-- 配置主鍵,是關(guān)聯(lián)Order的唯一標(biāo)識(shí) -->
        <id property="id" column="oid" />
        <result property="number" column="number" />
        <result property="createtime" column="createtime" />
        <result property="note" column="note" />
    </collection>
</resultMap>

<!-- 一對多關(guān)聯(lián),查詢訂單同時(shí)查詢該用戶下的訂單 -->
<select id="queryUserOrder" resultMap="userOrderResultMap">
    SELECT
    u.id,
    u.username,
    u.birthday,
    u.sex,
    u.address,
    o.id oid,
    o.number,
    o.createtime,
    o.note
    FROM
    `user` u
    LEFT JOIN `order` o ON u.id = o.user_id
</select>

逆向工程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容