1. 程式人生 > >Java框架-mybatis連線池、動態sql和多表查詢

Java框架-mybatis連線池、動態sql和多表查詢

1. mybatis連線池

  • 通過SqlMapConfig.xml設定dataSource type實現連線池的配置

1.1 dataSource標籤type屬性值含義

type=”POOLED”: MyBatis 會建立 PooledDataSource 例項

type=”UNPOOLED” : MyBatis 會建立 UnpooledDataSource 例項

type=”JNDI”: MyBatis 會從 JNDI 服務上查詢 並獲取DataSource 例項

1.2 mybatis連線池及dataSource

1.2.1 mybatis連線池分類及關係

  • Mybatis 的資料來源分為三類:

    • UNPOOLED 不使用連線池的資料來源
    • POOLED 使用連線池的資料來源
    • JNDI 使用 JNDI 實現的資料來源
  • Mybaits連線池關係

    mybatis連線池關係

    PooledDataSource通過UnPooledDataSource例項物件,實際上是一種快取連線池機制

1.2.2 UnPooledDataSource連線池

獲取連線方式有兩種

  1. 通過使用者名稱和密碼獲取連線(實際上是將使用者名稱、密碼封裝到屬性集,再呼叫第二種方法獲取)
  2. 通過配置檔案獲取連線

在這裡插入圖片描述

1.2.3 PooledDataSource連線池(建議使用)

  • PooledDataSource在建立連線時候,會自動呼叫UnPooledDataSource中建立連線的方法

1.2.4 連接獲取時機

  • 在例項資料庫時不會建立連線,而是在真正進行資料庫操作的時候再獲取連線

2. Mybatis對映檔案的動態sql

部分業務邏輯是動態變化的,需要使用動態sql滿足需求。Mybatis框架中sql是寫在dao介面對映檔案中,Mybatis提供多種標籤用以使用動態sql

2.1 <if>標籤

  • 使用if標籤進行條件判斷
    • 屬性test:用於判斷表示式,返回boolean型別。其值為條件表示式

2.1.1 對映檔案

<!--
使用if條件語句 test屬性用以判斷,其屬性值為條件判斷語句
-->
<select id="findByConditon" parameterType="user" resultType="com.azure.entity.User">
    select * from user where 1=1
    <!--條件判斷並拼接sql語句-->
    <if test="id != 0">
         and id=#{id}
    </if>
    <if test="username != null">
         and username=#{username}
    </if>
</select>

2.2 <where>標籤

  • 使用where標籤拼接where條件
<!--使用where標籤拼接where條件-->
<select id="findByConditon" parameterType="user" resultType="com.azure.entity.User">
    select * from user
    <where>
        <!--條件判斷並拼接sql語句-->
        <if test="id != 0">
            and id=#{id}
        </if>
        <if test="username != null">
            and username=#{username}
        </if>
    </where>
</select>

2.3 <foreach>標籤

  • 使用foreach標籤遍歷引數

    屬性值:

    • collection:遍歷的集合(引數列表)
    • open:sql語句最先拼接的部分,遍歷開始
    • close:sql語句最後拼接的部分,遍歷結束
    • separator:每次遍歷時,sql語句拼接時以指定的分割符分割
    • item:儲存每次遍歷的結果
    • index:當前遍歷元素的索引

    標籤體:給每個item賦值,可使用#{}賦值

案例需求:根據多個id查詢使用者返回使用者集合

2.3.1 定義查詢擴充套件物件

  • 用於封裝多個引數
  • 對原有的QueryVo進行拓展優化
/**
 * 通過繼承User類,QueryVO類可以實現User所有屬性查詢以及擴充套件屬性
 */
public class QueryVo extends User{

    /*
    使用一個List封裝多個id值
     */
    private List<Integer> ids;

    public QueryVo(){
    }

    //getter&setter
    public List<Integer> getIds() {
        return ids;
    }
    public void setIds(List<Integer> ids) {
        this.ids = ids;
    }
}

2.3.2 dao層介面

List<User> findByCondition2(QueryVo queryVo);

2.3.3 dao對映檔案

<!--使用foreach標籤進行多id查詢
使用程式碼格式select * from user where 1=1 and id in (xx,xx,...)
格式:select * from user where 1=1 and id=xx orid=xx,...不能使用foreach標籤
-->
    <select id="findByCondition2" resultType="user" parameterType="user">
        select * from user
        <where>
            <if test="ids != null and ids.size() > 0">
                <foreach collection="ids" open="id in (" separator="," close=")" item="id">
                    #{id}
                </foreach>
            </if>
        </where>
    </select>

2.3.4 測試類

@Test
public void find2() {
    //封裝條件
    QueryVo queryVo = new QueryVo();
    List<Integer> ids = new ArrayList<Integer>();
    ids.add(47);
    ids.add(48);
    ids.add(49);
    queryVo.setIds(ids);

    //執行方法
    List<User> list = userDao.findByCondition2(queryVo);
    System.out.println(list);
}

2.4 Mybatis簡化sql語句

  • sql標籤:定義sql片段,可以將公用的sql抽取出來

    • 屬性值:id,為sql片段命名
  • include標籤:用於引用sql片段

    • 屬性值:refid,與引用的sql標籤的id對應
  • 如果引用其它 mapper.xml 的 sql 片段,則在引用時需要加上 namespace,如下: <include refid=*"*namespace.sql 片段”/>

<!--抽取公共sql語句-->
<sql id="selectUser">
    select * from user
</sql>
<select id="findByCondition2" resultType="user" parameterType="queryVo">
    <!--引用sql片段-->
    <include refid="selectUser"></include>
    <where>
        <if test="ids != null and ids.size() > 0">
            <foreach collection="ids" open=" id in (" separator="," close=")" item="id">
                #{id}
            </foreach>
        </if>
    </where>
</select>
  • 注意事項:
    • 何時進行抽取?如果相同sql程式碼出現2次以上,就要將相同程式碼抽取出來,便於後期維護
    • 強烈建議將sql抽取出來!!!!!

3. Mybatis的多表關聯查詢

以使用者、賬戶和角色表之間查詢為例

準備工作:

  1. 賬戶表

    DROP TABLE IF EXISTS account;
    
    CREATE TABLE account (
      accountId INT(11) NOT NULL COMMENT '編號',
      UID INT(11) DEFAULT NULL COMMENT '使用者編號',
      MONEY DOUBLE DEFAULT NULL COMMENT '金額',
      PRIMARY KEY  (accountId),
      KEY FK_Reference_8 (UID),
      CONSTRAINT FK_Reference_8 FOREIGN KEY (UID) REFERENCES USER (id)
    ) ENGINE=INNODB DEFAULT CHARSET=utf8;
    INSERT  INTO account(accountId,UID,MONEY) VALUES (1,46,1000),(2,45,1000),(3,46,2000);
    
  2. 角色表

    CREATE TABLE role (
      ID int(11) NOT NULL COMMENT '編號',
      ROLE_NAME varchar(30) default NULL COMMENT '角色名稱',
      ROLE_DESC varchar(60) default NULL COMMENT '角色描述',
      PRIMARY KEY  (ID)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    insert  into role(ID,ROLE_NAME,ROLE_DESC) values (1,'院長','管理整個學院'),(2,'總裁','管理整個公司'),(3,'校長','管理整個學校');
    
    

3.1 一對一

需求:查詢賬戶表,並把賬戶對應的使用者資訊顯示出來

3.1.1 需求分析

賬戶與使用者是一對一關係,一個賬戶只能對應一個使用者

實現一對一關係步驟:

  1. 建立專案;

  2. 建立實體類(賬戶)

    • 賬戶表屬性

    • 封裝User資料

  3. 介面編寫

  4. 配置對映檔案,裡面配置1to1的關係,讓Mybatis自動封裝多表資料

  5. 測試

3.1.2 建立實體類

public class Account  implements Serializable {
    private int accountId;
    private int uid;
    private double money;

    //封裝User資料,賬戶與使用者是一對一關係
    private User user;

    public Account() {
    }
    /*省略有參、toString、getter&setter*/
}

3.1.3 建立dao介面

public interface IAccountDao {
    //查詢所有賬戶及對應的使用者資訊
    List<Account> findAll();
}

3.1.4 配置dao介面對映檔案

  • 一對一關係中,返回值型別必須使用resultMap,用來封裝多表查詢的資料

  • 使用<association>標籤表示一對一關係的對映配置。

    屬性值有:

    • property:一對一關係的對應物件屬性名(本例是指賬戶物件對應的user物件屬性);
    • JavaType:對應物件屬性型別
    • column:外來鍵欄位
<?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="com.azure.dao.IAccountDao">
    <!--返回集的型別是Account型別,裡面需封裝account表資料和User物件-->
    <resultMap id="accountResultMap" type="account">
        <!--先建立account物件屬性與account表字段的對映關係-->
        <id property="accountId" column="accountId"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <!--建立user物件與User表字段的對映關係-->
        <!--
        使用association標籤標示一對一關係
        - property:一對一關係的對應物件屬性名(本例是指賬戶物件對應的user物件屬性);
        - JavaType:對應物件屬性型別(本例即User型別)
        - column:外來鍵欄位
        -->
        <association property="user" javaType="user" column="uid">
            <id property="id" column="id"></id>
            <result property="username" column="username"></result>
            <result property="birthday" column="birthday"></result>
            <result property="sex" column="sex"></result>
            <result property="address" column="address"></result>
        </association>
    </resultMap>
    <!--使用resultMap明確一對一關係。
    使用左外連線確保account表資料能全部顯示
    -->
    <select id="findAll" resultMap="accountResultMap">
        select * from account a left join user u on a.uid=u.id
    </select>
</mapper>

3.1.5 測試類

public class AccountDaoTest {
    private InputStream is;
    private SqlSession session;
    private IAccountDao accountDao;

    /**
     * 每次執行Junit前都會執行
     * @throws IOException
     */
    @Before
    public void before() throws IOException {
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        session = new SqlSessionFactoryBuilder().build(is).openSession();
        accountDao = session.getMapper(IAccountDao.class);
    }

    /**
     * 每次執行Junit後都會執行,提交事務和關閉資源
     * @throws IOException
     */
    @After
    public void close() throws IOException {
        //手動提交事務
        session.commit();
        //關閉資源
        session.close();
        is.close();
    }

    @Test
    public void find() throws IOException{
        List<Account> accounts = accountDao.findAll();
        System.out.println(accounts);
    }
}

3.2 一對多

需求:查詢使用者,並將使用者對應的賬戶顯示

3.2.1 需求分析

  • 使用者與賬戶是一對多的關係,一個使用者可以有多個賬戶
  1. 建立專案;

  2. 建立實體類(使用者)

    • 使用者表屬性

    • 封裝Account資料

  3. 介面編寫

  4. 配置對映檔案,裡面配置1ton的關係,讓Mybatis自動封裝多表資料

  5. 測試

3.2.2 建立實體類

public class User implements Serializable{
    private int id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    //封裝account賬戶表資料,用一個list封裝所有賬戶
    private List<Account> accounts;

    public List<Account> getAccounts() {
        return accounts;
    }

    public void setAccounts(List<Account> accounts) {
        this.accounts = accounts;
    }
      /*省略有參、toString、getter&setter*/
}

3.2.3 dao介面

public interface IUserDao {
    /*查詢所有使用者*/
    List<User> findAll();
}

3.2.4 介面對映檔案

  • 需要使用resultMap封裝多表查詢結果

  • 使用<collection>標籤表示一對一關係的對映配置。

    屬性值有:

    • property:指定集合在實體類中的屬性名;(本例是User類中的List<Account>的屬性名accounts)
    • ofType:指定集合元素的java型別
    • column:外來鍵
<!--返回集的型別是User型別,裡面需封裝user表資料和Account物件-->
<resultMap id="usersMap" type="user">
    <!--先建立user物件屬性與user表字段的對映關係-->
    <id property="id" column="id"></id>
    <result property="username" column="username"></result>
    <result property="birthday" column="birthday"></result>
    <result property="sex" column="sex"></result>
    <result property="address" column="address"></result>
    <!--建立user物件與account表字段的對映關係-->
    <!--
   使用<collection>標籤表示一對一關係的對映配置。
    屬性值有:
    - property:對應的集合名;
    - ofType:指定集合元素的型別(本例指List<Account> 的Account型別)
    -->
    <collection property="accounts" ofType="account">
        <id property="accountId" column="accountId"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
    </collection>
</resultMap>
<select id="findAll" resultMap="usersMap">
    select * from user u left join account a ON u.id = a.UID
</select>

3.2.5 測試類

public class UserDaoTest {
    private InputStream is;
    private SqlSession session;
    private IUserDao userDao;

    /**
     * 每次執行Junit前都會執行
     * @throws IOException
     */
    @Before
    public void before() throws IOException {
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        session = new SqlSessionFactoryBuilder().build(is).openSession();
        userDao = session.getMapper(IUserDao.class);
    }

    /**
     * 每次執行Junit後都會執行,提交事務和關閉資源
     * @throws IOException
     */
    @After
    public void close() throws IOException {
        //手動提交事務
        session.commit();
        //關閉資源
        session.close();
        is.close();
    }
    
    @Test
    public void findAll() {
        List<User> list = userDao.findAll();
        System.out.println(list);
    }
}

3.3 多對多

  • 所謂的多對多關係,實際上是有多個一對多關係組合起來,所以處理多對多關係,要轉換成一對多關係。

需求:查詢所有使用者,並顯示對應的角色

3.3.1 需求分析

使用者與角色是多對多的關係,一個使用者有多種角色,一種角色也有多個使用者,需要分別描述

3.3.1.1 使用者對角色的一對多
  1. 建立專案;
  2. 建立實體類
    • User類(User本身資料,List<Role> roles)
    • Role類(Role本身資料)
  3. 介面編寫
  4. 配置對映檔案,裡面配置1ton的關係,讓Mybatis自動封裝多表資料
  5. 測試
3.3.1.2 角色對使用者一對多
  1. 建立專案;
  2. 建立實體類
    • User類(User本身資料,List<Role> roles)
    • Role類(Role本身資料,List<User> users)
  3. 介面編寫
  4. 配置對映檔案,裡面配置1ton的關係,讓Mybatis自動封裝多表資料
  5. 測試
3.3.1.3 使用者表與角色表分析

兩個表之間並無主鍵連線,無法單純用兩個表去描述表之間的關係,故需要新增使用者角色關係表用以描述關係。

DROP TABLE IF EXISTS user_role;

CREATE TABLE user_role (
  UID int(11) NOT NULL COMMENT '使用者編號',
  RID int(11) NOT NULL COMMENT '角色編號',
  PRIMARY KEY  (UID,RID),
  KEY FK_Reference_10 (RID),
  CONSTRAINT FK_Reference_10 FOREIGN KEY (RID) REFERENCES role (ID),
  CONSTRAINT FK_Reference_9 FOREIGN KEY (UID) REFERENCES user (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert  into user_role(UID,RID) values (41,1),(45,1),(41,2);

3.3.2 實體類

Role類

public class Role  implements Serializable {
    private int id;
    private String roleName;
    private String roleDesc;    
    //封裝User使用者表資料,使用List封裝
    private List<User2> user2s;
    /*省略建構函式、toString、getter&setter
}

User類

這裡新建一個User2,避免與上面的User類衝突

public class User2  implements Serializable {
    private int id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    //封裝role角色表資料,使用List封裝
    private List<Role> roles;
    /*省略建構函式、toString、getter&setter*/
}

3.3.3 使用者對角色一對多

3.3.3.1 dao層介面
/*
查詢所有使用者,Role有關
 */
List<User2
            
           

相關推薦

Java框架-mybatis連線動態sql查詢

1. mybatis連線池 通過SqlMapConfig.xml設定dataSource type實現連線池的配置 1.1 dataSource標籤type屬性值含義 type=”POOLED”: MyBatis 會建立 PooledDataSource 例項

Mybatis連線動態sql丶抽取sql語句

當實體類的屬性(uid)與資料庫的欄位(id)不一致的時候 對於增刪改: 只需在傳入引數後的佔位符中把對應的屬性傳遞進去就行 對於查詢: 1. 可以通過資料庫的別名來解決 select id as uid from user 2. 可以使用r

Java框架-mybatis延遲載入快取註解開發

1. 延遲載入 1.1 概念 在需要用到資料時才進行載入,不需要用到資料時就不載入資料。也稱作懶載入 好處:先從單表查詢,需要時再從關聯表去關聯查詢,大大提高資料庫效能 缺點:在大批量資料查詢時,由於查詢會耗時,可能導致使用者等待時間變長,影響使用者體驗

Java框架資料庫連線

Java框架資料庫連線池比較(c3p0,dbcp和proxool)  現在常用的開源資料連線池主要有c3p0,dbcp和proxool三種,其中: ¨         hiber

Java框架資料庫連線比較(c3p0,dbcpproxool)

現在常用的開源資料連線池主要有c3p0,dbcp和proxool三種,其中:  ¨         hibernate開發組推薦使用c3p0;  ¨         spring開發組推薦使用dbcp (dbcp連線池有weblogic連線池同樣的問題,就是強行關閉連

Mybatis——傳入POJO對象,動態SQL關系

this h標簽 根據 strong src 實現 圖片 tis his 傳入POJO對象 QueryVo.java public class QueryVo implements Serializable{ private User user; pu

SSM框架學習-MyBatisSQL對映檔案——實現高階結果對映查詢

SSM框架學習-MyBatis篇 SQL對映檔案——實現高階結果對映(多表查詢) 問題情境:比如有張表,使用者和使用者詳情,這兩張表裡面沒長表都有一個id欄位,這兩個表的id欄位都是對應的。 實體類裡面分別對應兩個實體類,user和userdetail,還有一個很重要的實

MyBatis中resultTyperesultMap元素分步關聯查詢

MyBatis select標籤, 常用元素有:id、parameterType、resultType、resultMap, id:配合Mapper的全限定名,聯合成為一個唯一的標識,使用者標識這條SQL。 parameterType:表示這條SQL接受的引數型別,可以是MyBatis系統定

Sql語句查詢更新

//多表查詢 select 表1.表1欄位, 表2.表2欄位 from 表1 inner join 表2 on 表1.Id=表2.Id //多表更新。讓A表的某欄位和B表的某欄位相同 update 表A set 表A.表A 欄位=表B.表B欄位 from 表B WHERE 表A

MySQL學習(三分組查詢查詢

一、分組查詢1.MySQL查詢函式    函式的分類:    1,單行函式:將每條資料進行獨立的計算,然後每條資料得到一條結果。    2,多行函式:多條資料同時計算,最終得到一條結果資料。也成為聚集函式、分組函式, 主要用於完成一些統計功能。2.什麼是分組?    針對於班

SQL筆記一:單查詢查詢

軟體相關不可避免的要用到資料庫相關技巧,對於測試來說最重要的是掌握資料庫的查詢技巧。 1.單表查詢 1.1無條件查詢特定欄位 語法:select 欄位A,欄位B……,欄位N from 表名 ,例如:select id,name from student      在stud

SQL server 查詢與檢視的使用

use Saijie    create table goods1(    商品編號  int primary key identity(1,1),--主鍵,自增    商品名稱  varchar(20) unique,  --唯一鍵    商品價格  decimal(5,

SQL判斷語句用法查詢

1.格式化時間sql語句   本例中本人隨便做了兩張表,和實際不是很相符,只是想說明sql語句的寫法。   例1表格式如下:      需求:查詢出本表,但需要使time欄位的時間格式為yyyy-MM-dd,比如:2013-08-13   sql寫法:   S

sql語句查詢(學生/課程表/教師/成績 )

問題及描述: --1.學生表 Student(S#,Sname,Sage,Ssex) --S# 學生編號,Sname 學生姓名,Sage 出生年月,Ssex 學生性別 --2.課程表 Course(C#,Cname,T#) --C# --課程編號,Cname 課程名稱,T# 教師編號 --3.教師表 Te

MyBatis從入門到精通(三):MyBatis XML方式的基本用法之查詢

最近在讀劉增輝老師所著的《MyBatis從入門到精通》一書,很有收穫,於是將自己學習的過程以部落格形式輸出,如有錯誤,歡迎指正,如幫助到你,不勝榮幸! 1. 多表查詢 上篇部落格中,我們示例的2個查詢都是單表查詢,但實際的業務場景肯定是需要多表查詢的,比如現在有個需求: 查詢某個使用者擁有的所有角色。這個需求

Java框架-Spring的jdbc連線及事務管理

1. Spring的AOP程式設計 1.1 純xml程式設計 <!--通知配置型別--> <aop:config> <!--設定切面--> <aop:aspect ref="logger"> <!-

MyBatis入門(二)—— 輸入映射輸出映射動態sql關聯查詢

輸出類型 sql name屬性 一對一 test HA h標簽 自動 CI p.p4 { margin: 0.0px 0.0px 0.0px 10.0px; font: 10.5px "PingFang SC" } p.p6 { margin: 0.0px 0.0px 0.

Java打造RPC框架(五):連線

在上一篇的文章中https://blog.csdn.net/we_phone/article/details/79053472 我初步完成了整個RPC框架的搭建,從服務呼叫到服務發現再到負載均衡,這一篇開始進行的是一系列我所知的優化操作 這一篇我講的是連線池,比較簡單,詳細程式碼已託管到gi

mybaits(查詢與別名日誌框架顯示sql語句物件屬性資料庫表字段不匹配resultMap使用mysql資料查詢分頁執行sql儲存過程動態SQL語句)

主要是各種配置檔案,建議把整個專案搬到自己電腦上慢慢看。 建立maven專案 首先是各種配置檔案: pom.xml: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://m

JDBC/InvocationHandler動態代理實現資料庫連線資料來源

Java的JDBC程式設計中,資料庫的連線和關閉是十分耗費資源的。當對資料庫的訪問不是很頻繁時,可以在每次訪問資料庫時建立一個連線,用完之後關閉。但是,對於一個複雜的資料庫應用,頻繁的建立、關閉連線,會極大的減低系統性能,造成瓶頸。所以可以使用資料庫連線池來達到