国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

Java的MyBatis框架中實現多表連接查詢和查詢結果分頁

2019-11-26 14:27:20
字體:
來源:轉載
供稿:網友

實現多表聯合查詢

還是在david.mybatis.model包下面新建一個Website類,用來持久化數據之用,重寫下相應toString()方法,方便測試程序之用。

package david.mybatis.model;import java.text.SimpleDateFormat;import java.util.Date;public class Website {  private int id;  private String name;  private int visitorId;  private int status;  private Date createTime;  private Visitor visitor;  public Website() {    // TODO Auto-generated constructor stub    createTime = new Date();    visitor = new Visitor();  }  public Website(String name, int visitorId) {    this.name = name;    this.visitorId = visitorId;    visitor = new Visitor();    status = 1;    createTime = new Date();  }  public int getId() {    return id;  }  public void setId(int id) {    this.id = id;  }  public Visitor getVisitor() {    return visitor;  }  public void setVisitor(Visitor visitor) {    this.visitor = visitor;  }  public String getName() {    return name;  }  public void setName(String name) {    this.name = name;  }  public int getStatus() {    return status;  }  public void setStatus(int status) {    this.status = status;  }  public Date getCreateTime() {    return createTime;  }  public void setCreateTime(Date createTime) {    this.createTime = createTime;  }  public int getVisitorId() {    int id = 0;    if (visitor == null)      id = visitorId;    else      id = visitor.getId();    return id;  }  public void setVisitorId(int visitorId) {    this.visitorId = visitorId;  }  @Override  public String toString() {    StringBuilder sb = new StringBuilder(String.format("Website=> {Id:%d, Name:%s, CreateTime:%s}/r/n", id, name,        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(createTime)));    if (visitor != null)      sb.append(String.format("Visitor=> %s", visitor.toString()));    return sb.toString();  }}

在david.mybatis.demo下面分別新建相應的操作接口:

package david.mybatis.demo;import java.util.List;import david.mybatis.model.Website;public interface IWebsiteOperation {    public int add(Website website);    public int delete(int id);    public int update(Website website);    public Website query(int id);    public List<Website> getList();  }

在mapper文件夾下新建WebsiteMapper.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"><mapper namespace="david.mybatis.demo.IWebsiteOperation">  <sql id="getListSql">    select id,    name, VisitorId, status, createTime from Website    where status>0  </sql>  <insert id="add" parameterType="Website" useGeneratedKeys="true"    keyProperty="Id">    insert into Website (Name, VisitorId, Status, CreateTime)    values (#{name}, #{visitorId}, #{status}, #{createTime})  </insert>  <delete id="delete" parameterType="int">    delete from website where    status>0 and id = #{id}  </delete>  <update id="update" parameterType="Website">    update website set    name=#{name} where status>0 and id=#{id}  </update>  <select id="query" parameterType="int" resultMap="websiteRs">    select    Website.id siteId, Website.name siteName, Visitor.Id visitorId,    Visitor.name visitorName,    Website.status siteStatus, Website.createtime    siteCreateTime from Website    inner join Visitor on Website.visitorid =    Visitor.id where Website.status>0 and    Website.id=#{id}  </select>  <resultMap type="Website" id="websiteRs">    <id column="siteId" property="id" />    <result column="siteName" property="name" />    <result column="siteStatus" property="status" />    <result column="siteCreateTime" property="createTime" />    <association property="visitor" javaType="Visitor" resultMap="visitorRs" />  </resultMap>  <resultMap type="Visitor" id="visitorRs">    <id column="visitorId" property="id" />    <result column="visitorName" property="name" />  </resultMap>  <select id="getList" resultMap="websiteByVisitorIdRs">  <include refid="getListSql" />  </select>  </mapper>

這里今天主要說的就是那個查,現在我們想要查詢網站的同時分別把相應的訪問者信息一起拿出來,怎么做呢,大家可以參照配置中的query,寫下聯表查詢的SQL,

這里主要要注意的是,Website實體與Visit的實體里面Id與Name這2個屬性都是一樣的,所以為了避免映射出現出錯現象,把相應的查詢結果列起上不一樣的別名,這樣綁定的時候就可以避免。

假如我像下面一樣配置會得到什么呢?

<select id="query" parameterType="int" resultMap="websiteRs">  select  Website.id, Website.name siteName, Visitor.Id,  Visitor.name visitorName,  Website.status siteStatus, Website.createtime  siteCreateTime from Website  inner join Visitor on Website.visitorid =  Visitor.id where Website.status>0 and  Website.id=#{id}</select><resultMap type="Website" id="websiteRs">  <id column="id" property="id" />  <result column="siteName" property="name" />  <result column="siteStatus" property="status" />  <result column="siteCreateTime" property="createTime" />  <association property="visitor" javaType="Visitor"    resultMap="visitorRs" /></resultMap><resultMap type="Visitor" id="visitorRs">  <id column="id" property="id" />  <result column="visitorName" property="name" /></resultMap>

201646152922153.png (685×113)

有木有發覺,Visitor的Id也變成2了,這個其實它默認映射了Website的ID,因為SQL語句查詢出來的結果2個ID都是變成2了,有人會問為什么不是4呢,因為他默認匹配第一個如果你把Website.Id與Visit.Id的位置,相互換下就會發現結果又神奇的變了

201646153012231.png (732×115)

所以需要起個別名避免這種情況,這樣你就會發現真相其實只有一個就是下面的:

201646153042322.png (747×120)

大家可以看到其實多表處理resultMap的方式和單表是一致的,也無非是吧列明與Javabean屬性名成對應上去,可以看到在Website的<resultMap>節點里面前臺另外一個resultMap,他就是代表Visit實體所需要映射的實體,可以使用以下方式進行關聯

<association property="visitor" javaType="Visitor" resultMap="visitorRs" />

其中的visitor就是Website實體中的visit字段名,必須保證名稱一致,否則就會拋出There is no getter for property named 'XXX' in 'class david.mybatis.model.Website'的異常,這在上幾章已經講述了,當然如果你覺得不用嵌套resultMap也行,嵌套也是出于其他地方可以還要用到這個配置那就提煉出來的過程,也是抽象出來的一種思想。具體使用<resultMap>中的ID與Result可以從官網查找相應區別說明:http://mybatis.github.io/mybatis-3/sqlmap-xml.html#Result_Maps

這樣,一個簡單的多表聯合查詢就出來啦~,如果還有更加復雜的查詢業務費是在這個基礎上些許的變通修改。

分頁效果邏輯
下面要講的是關于一個業務問題中我們常碰到的分頁問題。在開發web項目的時候我們經常會使用到列表顯示,一般我們都會用一些常用的列表控件例如,datatables(個人感覺十分不錯),easy ui下面的那些封裝好的表格控件。

  思路:在這些控件里要達到分頁的效果,一般都會傳2個參數,第一個是表示當前頁的索引(一般從0開始),第二個表示當前頁展示多少條業務記錄,然后將相應的參數傳遞給List<T> getList(PagenateArgs args)方法,最終實現數據庫中的分頁時候我們可以使用limit關鍵詞(針對mysql)進行分頁,如果是oracle或者sql server他們都有自帶的rownum函數可以使用。

  針對上述思路,首先我們需要還是一如既往的在demo.mybatis.model下面新建一個名為PagenateArgs的分頁參數實體類與一個名為SortDirectionEnum的枚舉類,里面包含當前頁面索引pageIndex, 當前頁展示業務記錄數pageSize, pageStart屬性表示從第幾條開始,(pageStart=pageIndex*pageSize)因為limit關鍵詞用法是表示【limit 起始條數(不包含),取幾條】,orderFieldStr排序字段,orderDirectionStr 排序方向,所以具體創建如下:
package david.mybatis.model;

/* * 分頁參數實體類 */public class PagenateArgs {  private int pageIndex;  private int pageSize;  private int pageStart;  private String orderFieldStr;  private String orderDirectionStr;  public PagenateArgs() {    // TODO Auto-generated constructor stub  }  public PagenateArgs(int pageIndex, int pageSize, String orderFieldStr, String orderDirectionStr) {    this.pageIndex = pageIndex;    this.pageSize = pageSize;    this.orderFieldStr = orderFieldStr;    this.orderDirectionStr = orderDirectionStr;    pageStart = pageIndex * pageSize;  }  public int getPageIndex() {    return pageIndex;  }  public int getPageStart() {    return pageStart;  }  public int getPageSize() {    return pageSize;  }  public String orderFieldStr() {    return orderFieldStr;  }  public String getOrderDirectionStr() {    return orderDirectionStr;  }}package david.mybatis.model;/* * 排序枚舉 */public enum SortDirectionEnum {  /*   * 升序   */  ASC,    /*   * 降序   */  DESC}

  完成上面的步驟以后我們在IVisitorOperation接口類中繼續添加一個方法public List<Visitor> getListByPagenate(PagenateArgs args),前幾章中我們其實已經有getList方法了,這次的分頁其實也就是在這個的基礎上稍加改動即可,IVisitorOperation接口類改動后如下所示:

package david.mybatis.demo;import java.util.List;import david.mybatis.model.PagenateArgs;import david.mybatis.model.Visitor;import david.mybatis.model.VisitorWithRn;public interface IVisitorOperation {  /*   * 基礎查詢   */  public Visitor basicQuery(int id);  /*   * 添加訪問者   */  public int add(Visitor visitor);    /*   * 刪除訪問者   */  public int delete(int id);    /*   * 更新訪問者   */  public int update(Visitor visitor);    /*   * 查詢訪問者   */  public Visitor query(int id);    /*   * 查詢List   */  public List<Visitor> getList();    /*   * 分頁查詢List   */  public List<Visitor> getListByPagenate(PagenateArgs args);  }

  接下來我們就要開始動手改動我們的VisitorMapper.xml配置文件了,新增一個<select>節點id與參數類型參照前幾章的方式配置好,如下此處新增的id就為getListByPagenate,配置好以后如下

<?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"><mapper namespace="david.mybatis.demo.IVisitorOperation">  <!-- useGeneratedKeys="true"代表是否使用自增長序列, keyProperty="Id"指定自增長列是哪一列, parameterType="Visitor"指定IVisitorOperation接口類中定義中所傳的相應類型 -->  <insert id="add" parameterType="Visitor" useGeneratedKeys="true"    keyProperty="Id">    insert into Visitor (Name, Email, Status, CreateTime)    values (#{name}, #{email}, #{status}, #{createTime})  </insert>  <delete id="delete" parameterType="int">    delete from Visitor where    status>0 and id = #{id}  </delete>  <update id="update" parameterType="Visitor">    update Visitor set Name =    #{name}, Email=#{email}, Status=#{status} where id=#{id} and Status>0;  </update>  <select id="query" parameterType="int" resultType="Visitor">    select Id,    Name, Email, Status, CreateTime from visitor where id=#{id} and    Status>0 order by Id  </select>  <select id="basicQuery" parameterType="int" resultType="Visitor">    select *    from visitor where id=#{id} and    Status>0 order by Id  </select>  <select id="getList" resultMap="visitorRs">    <include refid="getListSql" />  </select>  <sql id="getListSql">    select * from Visitor where    status>0  </sql>  <!-- 以下為新增部分用來分頁,orderBySql這個提取出來是為了后面有示例復用 -->  <resultMap type="Visitor" id="visitorRs">    <id column="Id" property="id" />    <result column="Name" property="name" />    <result column="Email" property="email" />    <result column="Status" property="status" />    <result column="CreateTime" property="createTime" />  </resultMap>  <select id="getListByPagenate" parameterType="PagenateArgs"    resultType="Visitor">    select * from (    <include refid="getListSql" /> <include refid="orderBySql"/>    ) t <!-- #{}表示參數化輸出,${}表示直接輸出不進行任何轉義操作,自己進行轉移 -->    <if test="pageStart>-1 and pageSize>-1">      limit #{pageStart}, #{pageSize}    </if>  </select>  <sql id="orderBySql">    order by ${orderFieldStr} ${orderDirectionStr}  </sql></mapper>

  在上面你會發現有類似,下圖中的配置,這里面的字段屬性都是針對PagenateArgs參數類中的屬性名,保持一致。

<if test="pageStart>-1 and pageSize>-1">  limit #{pageStart}, #{pageSize}</if>

   在DemoRun類中創建測試方法:

/* * 分頁參數 */public static void queryVisitorListWithPagenate(int pageIndex, int pageSize, String orderField, String orderDire) {  PagenateArgs args = new PagenateArgs(pageIndex, pageSize, orderField, orderDire);  SqlSession session = MybatisUtils.getSqlSession();  IVisitorOperation vOperation = session.getMapper(IVisitorOperation.class);  List<Visitor> visitors = vOperation.getListByPagenate(args);  for (Visitor visitor : visitors) {    System.out.println(visitor);  }  MybatisUtils.closeSession(session);  MybatisUtils.showMessages(CRUD_Enum.List, visitors.size());}
DemoRun.queryVisitorListWithPagenate(0, 100, "id", SortDirectionEnum.DESC.toString());

運行后下測試結果,先按Id倒序排列,查的Visitor表一共有14條記錄,

201646153410351.png (598×334)

假設我們取在第2頁取5條,執行下面也就是6-10條數據,這樣傳參數就行了

DemoRun.queryVisitorListWithPagenate(1, 5, "id", SortDirectionEnum.DESC.toString());

結果如下:

201646153410351.png (598×334)

這樣就自己實現了的一個分頁邏輯啦~^0^,這里需要注意的就是我這邊orderFieldStr字段是沒有做過任何判斷的,理論上要處理下防止錯誤了列名傳進去,不過現在網上應該有現成封裝好的東西,大家也可以去google下,這里只是給個思路演示下怎么用mybatis分頁。

  完成這個后,因為是Mysql的關系所以在查詢結果里他沒有自帶rownum序列ID,所以查看測試數據是第幾條的時候可能不明顯,不zao急,我們可以自己動手豐衣足食改造下上面的方法,這里我重新在model包里新建一個一模一樣的VisitorWithRn實體里面多帶一個rownum參數持久化返回的RownumID,如下:

package david.mybatis.model;import java.text.SimpleDateFormat;import java.util.Date;public class VisitorWithRn {  private int id;  private String name;  private String email;  private int status;  private Date createTime;  private int rownum;  public VisitorWithRn() {    // TODO Auto-generated constructor stub    createTime = new Date();  }  public VisitorWithRn(String name, String email) {    this.name = name;    this.email = email;    this.setStatus(1);    this.createTime = new Date();  }  public int getId() {    return id;  }  public void setName(String name) {    this.name = name;  }  public String getName() {    return name;  }  public void setEmail(String email) {    this.email = email;  }  public String getEmail() {    return email;  }  public Date getCreateTime() {    return createTime;  }  public int getStatus() {    return status;  }  public void setStatus(int status) {    this.status = status;  }  public int getRownum() {    return rownum;  }  public void setRownum(int rownum) {    this.rownum = rownum;  }  @Override  public String toString() {    // TODO Auto-generated method stub    return String.format("{Rownum:%d, Id: %d, Name: %s, CreateTime: %s}", rownum, id, name,        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(createTime));  }}

在IVisitorOperation里面在新建一個名為 public List<VisitorWithRn> getListByPagenateWithRn(PagenateArgs args)的方法,同樣我們需要在VisitorMapper中配置下相應<select>節點與腳本,此處唯一的不同就是需要改下sql腳本,如下:

<?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"><mapper namespace="david.mybatis.demo.IVisitorOperation">  <!-- useGeneratedKeys="true"代表是否使用自增長序列, keyProperty="Id"指定自增長列是哪一列, parameterType="Visitor"指定IVisitorOperation接口類中定義中所傳的相應類型 -->  <insert id="add" parameterType="Visitor" useGeneratedKeys="true"    keyProperty="Id">    insert into Visitor (Name, Email, Status, CreateTime)    values (#{name}, #{email}, #{status}, #{createTime})  </insert>  <delete id="delete" parameterType="int">    delete from Visitor where    status>0 and id = #{id}  </delete>  <update id="update" parameterType="Visitor">    update Visitor set Name =    #{name}, Email=#{email}, Status=#{status} where id=#{id} and Status>0;  </update>  <select id="query" parameterType="int" resultType="Visitor">    select Id,    Name, Email, Status, CreateTime from visitor where id=#{id} and    Status>0 order by Id  </select>  <select id="basicQuery" parameterType="int" resultType="Visitor">    select *    from visitor where id=#{id} and    Status>0 order by Id  </select>  <select id="getList" resultMap="visitorRs">    <include refid="getListSql" />  </select>  <sql id="getListSql">    select * from Visitor where    status>0  </sql>  <resultMap type="Visitor" id="visitorRs">    <id column="Id" property="id" />    <result column="Name" property="name" />    <result column="Email" property="email" />    <result column="Status" property="status" />    <result column="CreateTime" property="createTime" />  </resultMap>  <select id="getListByPagenate" parameterType="PagenateArgs"    resultType="Visitor">    select * from (    <include refid="getListSql" /> <include refid="orderBySql"/>    ) t <!-- #{}表示參數化輸出,${}表示直接輸出不進行任何轉義操作,自己進行轉移 -->    <if test="pageStart>-1 and pageSize>-1">      limit #{pageStart}, #{pageSize}    </if>  </select>  <!--提煉出來為了2個示例共用下 -->  <sql id="orderBySql">    order by ${orderFieldStr} ${orderDirectionStr}  </sql>  <!-- 帶rownum的SQL腳本書寫方式 -->  <resultMap type="VisitorWithRn" id="visitorWithRnRs">    <id column="Id" property="id" />    <result column="Name" property="name" />    <result column="Email" property="email" />    <result column="Status" property="status" />    <result column="CreateTime" property="createTime" />    <result column="Rownum" property="rownum" />  </resultMap>  <select id="getListByPagenateWithRn" resultMap="visitorWithRnRs">    <!-- #{}表示參數化輸出,${}表示直接輸出不進行任何轉義操作,自己進行轉移 -->    select t.Rownum, t.Id, t.Name, t.Email, t.Status, t.CreateTime from (<include refid="getListSqlContainsRn" /> <include refid="orderBySql"/>) t    <if test="pageStart>-1 and pageSize>-1">      limit #{pageStart}, #{pageSize}    </if>  </select>  <sql id="getListSqlContainsRn">    select @rownum:=@rownum+1 Rownum,    result.id, result.name, result.email, result.status, result.createTime    FROM (    select @rownum:=0, Visitor.* from Visitor where    status>0) result  </sql></mapper>

接下來剩下的就是如剛才在DemoRun下面添加測試方法,這里就不貼圖了,完成后你可以看到剛剛的6-10條數據會變成如下

201646153839223.png (620×298)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 武宣县| 呼和浩特市| 安国市| 甘孜县| 兰坪| 南宫市| 康保县| 建始县| 扶风县| 佛学| 尼玛县| 固始县| 博兴县| 根河市| 潞西市| 四川省| 塘沽区| 阳西县| 渭源县| 哈尔滨市| 福泉市| 和顺县| 曲阜市| 贵德县| 宣化县| 城市| 肃南| 白银市| 永兴县| 巴东县| 常州市| 格尔木市| 措美县| 太湖县| 盐亭县| 拉孜县| 甘孜县| 筠连县| 米林县| 阳朔县| 洛阳市|