1. 程式人生 > >MyBatis學習筆記(三)模糊查詢專題

MyBatis學習筆記(三)模糊查詢專題

首發於我的部落格 和尚的部落格
本文講解,用介面代理模式實現mybatis的模糊查詢,講解#{}和${}兩個的區別,XML檔案中五個特殊字串不允許使用,小於號的解決問題。

1.關於介面代理模式和傳統模式的區別

  • 傳統模式:在筆記(二)就是採用的這個模式:

    1. 需要寫介面,介面實現類,測試類,
    2. 對映檔案名稱空間為持久化類的全路徑
  • 介面代理模式:本筆記之後所有采用這個模式:

    1. 只需要寫介面,在測試類中呼叫,介面程式設計: 什麼是介面? 簡單理解:介面就是定義規範

    2. 介面返回型別跟你設定的resultMap或者resultType對應上即可,但是會根據你返回的型別完成selectone或者selectList操作

    3. 接口裡方法如何寫:sql語句返回的結果集型別 sql語句的id(要傳的值);

      • eg:List getSkillLike02(String name);

      List為SQL語句返回的結果集型別,getSkillLike02為對映檔案中SQL語句的id,String name是傳給對映檔案的值

    4. 對映檔案名稱空間為介面的全路徑

    5. 可以根據介面的返回型別自動判斷使用selectOne還是selectList

      • eg:返回的是一個物件的為one,返回的是list的就是List,如果是List,也是List

2.MyBatis框架中獲取資料的形式有兩種方案 #{}和${}的區別?

  • #{}
    • 取值:
    • 方案一: 如果你是一個簡單的資料型別,那麼我們使用#{任意識別符號}
    • 方案二: 物件或者Map #{屬性或者KEY}
    • 如果使用#{}那麼它的模式方式為預處理模式
  • ${}
    • 你需要必須指明KEY或者屬性
    • 對資料不會進行轉義
    • 直接拼接到SQL語句上

3.XML檔案中有五個特殊字串不允許使用

  1. 方法一:用了轉義字元把>和<替換掉,然後就沒有問題了。

    附:XML轉義字元

  2. 方法二:

因為這個是xml格式的,所以不允許出現類似“>”這樣的字元,但是都可以使用

4.程式碼結構

5.資料庫屬性檔案

jdbc.properties

jdbc.mysql.driver=com.mysql.jdbc.Driver
jdbc.mysql.url=jdbc:mysql://localhost:3306/cy42_mss
jdbc.mysql.username=root jdbc.mysql.password=root

6.核心配置檔案

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--載入屬性檔案 -->
    <properties resource="jdbc.properties"/>
    <!--自定義設定型別的別名,也就是resultMap裡的type,避免包名已修改,在對映檔案裡修改多處地方-->
    <typeAliases>
        <!-- 方式一、com.hs.model.Skill這個類設定了別名hs,之後要用這個的話,直接寫hs -->
        <!--<typeAlias type="com.hs.model.Skill" alias="hs"/> -->
        <!-- 方式二、com.hs.model這個包下的類,要用的時候直接寫類名,比如用com.hs.model.Skill,直接寫Skill -->
        <package name="com.hs.model"/>
    </typeAliases>
    <!--配置資料庫的環境-->
    <environments default="development">
        <environment id="development">
            <!--事務管理器:保證資料的完整性和一致性   關鍵資訊  -->
            <!--框架:預設情況下CUD操作需要  手動提交事務
            (如同在Navicat中表中輸入了資料,沒有點那個小√,就是沒有提交事務,
            但是輸入insert語句,就自動提交事務了)  -->
            <transactionManager type="JDBC" />
            <!--使用的是連線池:百度java如何實行連線池的原理?  -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.mysql.driver}" />  <!--獲取值,${屬性檔案裡的變數名},也可以直接寫值-->
                <property name="url" value="${jdbc.mysql.url}" />  <!--獲取值,${屬性檔案裡的變數名},也可以直接寫值-->
                <property name="username" value="${jdbc.mysql.username}" /> <!--獲取值,${屬性檔案裡的變數名},也可以直接寫值-->
                <property name="password" value="${jdbc.mysql.password}" /> <!--獲取值,${屬性檔案裡的變數名},也可以直接寫值-->
            </dataSource>
        </environment>
    </environments>

    <!--載入對映檔案 ,也就是含sql語句的檔案-->
    <mappers>
         <!--告知對映檔案方式1,一個一個的配置-->
        <mapper resource="com/hs/model/SkillMapper.xml"/>
        <!-- 告知對映檔案方式2,自動掃描包內的Mapper介面與配置檔案 -->
        <!--<package name="com.hs.model"/>-->
    </mappers>
</configuration>

7.介面程式碼

SkillDao.java

package com.hs.dao;
/**
 * 介面代理模式實現操作,在xxDao介面中,定義方法:  sql語句返回的結果型別 sql語句的id(要傳的值);
 * 不用寫實現類,直接寫測試類,具體實現見測試類
 * sql的對映檔案的名稱空間跟介面的全路徑一致
 * 可以根據介面的返回型別自動判斷使用selectOne還是selectList eg:返回的是一個物件的為one,返回的是list的就是list,如果是List<Bean>,也是list
 */
import com.hs.model.Skill;

import java.util.List;
import java.util.Map;

public interface SkillDao {

    List<Skill> getSkillLike01();

    List<Skill> getSkillLike02(String name);

    List<Skill> getSkillLike03(String name);

    List<Skill> getSkillLike04(Map<String,Object> map);

    List<Skill> getSkillLike05(Map<String,Object> map);

}

8.持久化類

Skill.java

package com.hs.model;

public class Skill {
    private Integer skillid;
    private String skillname;
    private Integer num;

    public Integer getSkillid() {
        return skillid;
    }

    public void setSkillid(Integer skillid) {
        this.skillid = skillid;
    }

    public String getSkillname() {
        return skillname;
    }

    public void setSkillname(String skillname) {
        this.skillname = skillname;
    }

    public Integer getNum() {
        return num;
    }

    public void setNum(Integer num) {
        this.num = num;
    }

    @Override
    public String toString() {
        return "Skill{" +
                "skillid=" + skillid +
                ", skillname='" + skillname + '\'' +
                ", num=" + num +
                '}';
    }
}

9.對映檔案

SkillMapper.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=名稱空間,唯一不重複-->
<mapper namespace="com.hs.dao.SkillDao">  <!--名稱空間規則
傳統模式:(持久化類(實體化Bean)的類名全路徑com.hs.Skill)
介面代理模式:介面的全路徑-->

    <resultMap id="BaseResultMap" type="com.hs.model.Skill">
        <id column="skill_id" property="skillid"/>    <!--若有主鍵,主鍵用id標籤,其餘用result標籤-->
        <result column="skill_name" property="skillname"/>
        <result column="num" property="num"/>
    </resultMap>

    <!--1.模糊條件查詢是固定的,寫死在sql語句裡了-->
    <select id="getSkillLike01" resultMap="BaseResultMap">
        select skill_id,skill_name,num from skill where skill_name like '%s%'
    </select>

    <!--2.模糊條件是一個簡單的資料型別
        當你傳遞的為一個簡單的資料型別,那麼我們可以通過#{任意寫}進行傳值,  #{xx}是一種預處理模式,先sql語句裡是?
        然後接收到值了,再寫進去,會給你預設加   '',即為'#{}'
    -->
        <!--A、通過java程式碼拼接字串-->
    <select id="getSkillLike02" parameterType="string" resultMap="BaseResultMap">
        select skill_id,skill_name,num from skill where skill_name like #{name}
    </select>
        <!--B、通過SQL語句函式拼接字串 concat函式指字串拼接,-->
    <select id="getSkillLike03" parameterType="string" resultMap="BaseResultMap">
        select skill_id,skill_name,num from skill where skill_name like concat('%',#{name},'%')
    </select>
        <!--C、通過${}完成模糊查詢!!!但是不太推薦,${}不會預設加 '' ,也不是預處理模式,是直接在把值寫在了sql語句中,
            一般用於order by ${key或者屬性},一般只接受map或者物件
        -->
    <select id="getSkillLike04" parameterType="map" resultMap="BaseResultMap">
        select skill_id,skill_name,num from skill where skill_name like concat('%','${name}','%')
    </select>
    <!--${}的應用,排序-->
    <select id="getSkillLike05" parameterType="map" resultMap="BaseResultMap">
        select * from skill order by skill_id ${fs}
    </select>
</mapper>

10.封裝好的工具類

MyBatis.java

package com.hs.util;
/**
 * 知識點:
 * final修飾類:不能被繼承
 * 修飾方法:不能被重寫
 * 修飾變數:常量不可用變,但如果是物件,物件裡的值可以變
 *
 */
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MyBatisUtils {

    private MyBatisUtils() { }  //不允許例項化

    private static final String PATH = "mybatis-config.xml";
    private static InputStream inputStream;
    private static SqlSessionFactory sqlSessionFactory;

    static { //1.靜態程式碼塊,只是載入一次
        try {
            inputStream = Resources.getResourceAsStream(PATH);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("載入核心配置檔案失敗");
        }
    }

    public static SqlSession getSqlsession() {
        return sqlSessionFactory.openSession();
    }

    public static void closeSqlSession(SqlSession sqlSession) {
        if (sqlSession != null) {
            sqlSession.close();
        }
    }

}

11.日誌框架配置

log4j.properties

# 日誌配置檔案Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
# 如果要顯示SQL語句,那麼這個位置需要配置為名稱空間log4j.logger.名稱空間
log4j.logger.com.hs.dao.SkillDao=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

12.測試類

MyBatis.java

package com.hs.test;

import com.hs.dao.SkillDao;
import com.hs.util.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

/**
 * 介面代理模式實現操作,在xxDao介面中,定義方法:  sql語句返回的結果型別 sql語句的id(要傳的值);
 * 不用寫實現類,直接寫測試類,具體實現見測試類
 * sql的對映檔案的名稱空間跟介面的全路徑一致
 * 可以根據介面的返回型別自動判斷使用selectOne還是selectList eg:返回的是一個物件的為one,返回的是list的就是list,如果是List<Bean>,也是list
 */
public class MyBatisTest {

    /**
     * 1.模糊條件查詢是固定的,寫死在sql語句裡了
     */
    @Test
    public void getSkillLike01() {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
//          根據xml對映檔案,介面建立實現類代理   有點類似傳統模式的new UserMapperImpl()
            SkillDao skillDao = sqlSession.getMapper(SkillDao.class);
            System.out.println(skillDao.getSkillLike01());
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }

    }
    /**
     * 2.通過java程式碼拼接字串進行模糊查詢
     */
    @Test
    public void getSkillLike02() {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            String name = "%a%";
            SkillDao skillDao = sqlSession.getMapper(SkillDao.class);
            System.out.println(skillDao.getSkillLike02(name));
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }

    }
    /**
     * 3.通過sql語句函式拼接字串進行模糊查詢
     */
    @Test
    public void getSkillLike03() {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            String name = "s";
            SkillDao skillDao = sqlSession.getMapper(SkillDao.class);
            System.out.println(skillDao.getSkillLike03(name));
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }

    }

    /**
     * 4.通過${}拼接字串進行模糊查詢
     */
    @Test
    public void getSkillLike04() {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("name", "s");
            SkillDao skillDao = sqlSession.getMapper(SkillDao.class);
            System.out.println(skillDao.getSkillLike04(map));
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }

    }

    /**
     * 4.通過${}進行排序操作
     */
    @Test
    public void getSkillLike05() {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("fs", "DESC");
            SkillDao skillDao = sqlSession.getMapper(SkillDao.class);
            System.out.println(skillDao.getSkillLike05(map));
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }

    }

}