天天看點

mybaties學習筆記Junit1.簡介2.第一個mybatis程式3.CRUD4.XML配置5.解決屬性名和字段名不一緻的問題6.日志7.分頁8.使用注解開發9.Lombok10.多對一11.一對多12.動态SQL6.foreach(幾乎不用)7.SQL片段13.緩存(了解)14.Mybatis緩存Mybatis注意點

mybatis架構 持久層

Spring

Spring MVC 表示層

shiro 安全架構

git 版本控制工具

項目階段

Junit

使用Junit做單元測試的目的:

  • 友善運作代碼,人為檢視結果符不符合預期
  • 使用斷言測試讓機器去判斷結果符不符合預期,a開頭的很多junit斷言測試
    User one = UserDao.getOne(1);
    asserEquals(null,one);      

@Test注釋的方法成為測試用例

測試注解使用的要求:

  • 要注解在某個方法上
  • 該方法要求無參,傳回值為空,且為public

在test裡面添加參數

@Test(timeout=1000)

限時測試:timeout屬性指定毫秒值,要求該單元測試用例在規定時間内完成

@Before

作用于某個方法上

作用:所有的測試單元執行之前執行該方法,每執行一個測試單元就會執行一次Before

要求:

  • 要注解在某個方法上
  • 該方法要求無參,傳回值為空,且為public

@After

作用于某個方法上

作用:在所有單元測試用例之後執行該方法(多用于資源回收)

要求:

  • 要注解在某個方法上
  • 該方法要求無參,傳回值為空,且為public

@BeforeClass

在整個測試類的所有測試用例運作之前運作一次

  • 要注解在某個方法上
  • 該方法要求無參,傳回值為空,還要被public static修飾!!

@AfterClass

在整個測試類的所有測試用例運作完之後運作一次

  • 要注解在某個方法上
  • 該方法要求無參,傳回值為空,還要被public static修飾!!

@Ignore

忽略這個測試用例,但是會在總計結果中顯示統計資訊

@Runwith()

套件測試,同時測試多個測試類。所謂Runner提供單元你測試運作的環境,預設為Junit4.class

@RunWith(Suite.class)
@Suite.SuiteClasses(UserDaoImplTest.class,AppTest.class)      

@Suite.SuiteClasses指定該套件中包含了哪些測試類

1.簡介

  • MyBatis 是一款優秀的持久層架構
  • 它支援自定義 SQL、存儲過程以及進階映射。
  • MyBatis 免除了幾乎所有的 JDBC 代碼以及設定參數和擷取結果集的工作。
  • MyBatis 可以通過簡單的 XML 或注解來配置和映射原始類型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 對象)為資料庫中的記錄。
mybaties學習筆記Junit1.簡介2.第一個mybatis程式3.CRUD4.XML配置5.解決屬性名和字段名不一緻的問題6.日志7.分頁8.使用注解開發9.Lombok10.多對一11.一對多12.動态SQL6.foreach(幾乎不用)7.SQL片段13.緩存(了解)14.Mybatis緩存Mybatis注意點

1.1.擷取mybaties

  • maven倉庫:https://mvnrepository.com/artifact/org.mybatis/mybatis
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.6</version>
</dependency>
​      
  • github
  • 官方中文文檔:https://mybatis.org/mybatis-3/zh/index.html

1.2.持久層

Dao層(資料庫操作層),Service層(業務層),Control層(專門接收使用者請求層)。

  • 持久層:完成持久化工作的代碼塊
  • 層是界限十分明顯的
持久化是一個動作,持久層是一個概念。

1.3.為什麼需要Mybatis

  • 友善
  • 傳統的JDBC太複雜,簡化,架構,自動化
  • 幫助程式員将資料存入到資料庫中
  • 不用mybatis也可以,更容易上手
  • 用的人特别多

spring,spring mvc,springboot

2.第一個mybatis程式

步驟:搭建環境-》導入mybatis-》編寫代碼-》測試

搭建資料庫環境

2.1導入xml依賴

   <dependencies>
<!--        mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
<!--        mysql驅動-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>
<!--        測試工具junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
​
    </dependencies>      

2.2.建立一個maven子項目

  • 配置mybatis的核心配置檔案
    <?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核心配置檔案-->
    <configuration>
    <!--    environments配置多個環境-->
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
    <!--                在xml中&符号需要進行轉義&amp-->
                    <property name="url" value="jdbc:mysql:///mybatis"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                </dataSource>
            </environment>
        </environments>
    </configuration>      

2.3編寫mybatis工具類

//第一步從 XML 中建構 SqlSessionFactory
public class MybatisUtil {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        
    }
    //第二步既然有了 SqlSessionFactory,顧名思義,我們可以從中獲得 SqlSession 的執行個體。
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}
​      

2.4編寫代碼

  • 實體類
public class User {
    private int id;
    private String name;
    private String password;
​
    public int getId() {
        return id;
    }
​
    public void setId(int id) {
        this.id = id;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public String getPassword() {
        return password;
    }
​
    public void setPassword(String password) {
        this.password = password;
    }
​
    public User() {
    }
​
    public User(int id, String name, String password) {
        this.id = id;
        this.name = name;
        this.password = password;
    }
​
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}      
  • Dao接口
    public interface UserDao {
        List<User> getUserList();
    }
    ​      
  • 接口實作類
<?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命名空間綁定一個Maper接口-->
<mapper namespace="com.liu.Dao.UserDao">
<!--    id對應UserDao的方法,resultType對應實體類-->
   <select id="getUserList" resultType="com.liu.Pojo.User">
       select * from mybatis.user
   </select>
</mapper>      
mybaties學習筆記Junit1.簡介2.第一個mybatis程式3.CRUD4.XML配置5.解決屬性名和字段名不一緻的問題6.日志7.分頁8.使用注解開發9.Lombok10.多對一11.一對多12.動态SQL6.foreach(幾乎不用)7.SQL片段13.緩存(了解)14.Mybatis緩存Mybatis注意點

2.5測試

注意:

org.apache.ibatis.binding.BindingException: Type interface com.liu.Dao.UserMaper is not known to the MapperRegistry.

MapperRegistry是什麼?

核心配置檔案中注冊mapers

  • junit測試
public class UserDaoTest {
    @Test
    public void test() {
        //第一步擷取sqlSession對象
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        //執行SQL
        //方式一getMapper
        UserMaper mapper = sqlSession.getMapper(UserMaper.class);
        List<User> userList = mapper.getUserList();
​
        for (User user : userList) {
            System.out.println(user);
        }
        //關閉sqlSession
        sqlSession.close();
    }
}      

可能遇到的問題:

1.配置檔案沒有注冊

2.綁定接口錯誤

3.方法名不對

4.傳回類型不對

5.Maven導出資源問題

3.CRUD

1.namespace

namespace中的包名要和Mapper接口的報名一緻

2.select

選擇,查詢語句;

  • id:就是對應namespace中的方法名
  • resulType:sql語句執行的傳回值!
  • paramterType:參數類型!

1.編寫接口

2.編寫對應的mapper中的sql

3.測試

3.Insert

UserMapper:

 //插入一條記錄
    public void insertOne(User user);      

UserMapper.xml

<insert id="insertOne" parameterType="com.liu.Pojo.User">
        insert into user values (#{id},#{name},#{password})
    </insert>      

Test:

//插入使用者
    @Test
    public void insertOne(){
        SqlSession sqlSession = MybatisUtil.getsqlSession();
​
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.insertOne(new User(4,"liulang","123456"));
​
        //送出事務
        sqlSession.commit();
        sqlSession.close();
    }      

4.Update

UserMapper:

   //修改記錄
    public int alterUser(User user);      

UserMapper.xml

<update id="alterUser" parameterType="com.liu.Pojo.User">
        update user set name=#{name},password=#{password} where id=#{id};
    </update>      

Test:

 //修改資訊
    @Test
    public void alterUser(){
        SqlSession sqlSession = MybatisUtil.getsqlSession();
​
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int i = mapper.alterUser(new User(4, "liulang", "123"));
        if (i>0)
            System.out.println("修改成功");
        else
            System.out.println("修改失敗");
​
        //送出事務
        sqlSession.commit();
        sqlSession.close();
    }      

5.Delete

UserMapper:

//删除使用者
    public int deleteUser(int id);      

UserMapper.xml

 <delete id="deleteUser" parameterType="int">
        delete from user where id=#{id}
    </delete>      

Test:

  //删除使用者
    @Test
    public void deleteUser(){
        SqlSession sqlSession = MybatisUtil.getsqlSession();
​
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int i = mapper.deleteUser(4);
        if (i>0)
            System.out.println("删除成功");
        else
            System.out.println("删除失敗");
​
        //送出事務
        sqlSession.commit();
        sqlSession.close();
    }      

注意:增删改都需要送出事務才會生效!!! sqlSession.commit();

6.錯誤

  1. namespace="com.liu.Mapper.UserMapper";必須寫詳細路徑
  2. sql語句标簽錯誤
  3. 注冊mapper;resource的路徑要用/而不是點
    <mappers>
        <mapper resource="com/liu/Mapper/UserMapper.xml"/>
    </mappers>      

4.maven資源導出問題

<build>
        <resources>
<!--            設定正常情況的resources目錄下的properties檔案-->
            <resource>
<!--                配置路徑-->
                <directory>src/main/resources</directory>
                <includes>
<!--                    包含什麼檔案-->
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
            </resource>
<!--      設定java路徑的properties檔案-->
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>      

7.非常實用的Map

如果我們的實體類或資料中的表,字段過多,我們考慮使用Map。

修改或添加部分資訊:

UserMapper:

//使用map修改部分資料
    public int alterUser2(Map<String,Object> map);      

UserMapper.xml

<update id="alterUser2" parameterType="map">
        update user set  name=#{username}  where id=#{userid};
    </update>      

Test:

   //使用map更新部分資訊
    @Test
    public void alterUser2(){
        SqlSession sqlSession = MybatisUtil.getsqlSession();
​
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("username","李小盛");
        map.put("userid",3);
        int i = mapper.alterUser2(map);
        if (i>0)
            System.out.println("修改成功");
        else
            System.out.println("修改失敗");
​
        //送出事務
        sqlSession.commit();
        sqlSession.close();
    }      

根據多個條件查詢資訊:

UserMapper:

//指定多條件查詢
    public User getUserById2(Map<String,Object> map);      

UserMapper.xml

<select id="getUserById2" parameterType="map" resultType="com.liu.Pojo.User">
        select * from user where id=#{id} and name=#{name}
    </select>      

Test:

 @Test
    public void getUserById2(){
        SqlSession sqlSession = MybatisUtil.getsqlSession();
​
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("id",3);
        map.put("name","李小盛");
        User user = mapper.getUserById2(map);
​
        System.out.println(user);
​
        sqlSession.close();
    }      

Map傳遞參數,直接在sql中取出key即可。

使用Map的時候一定要注意map裡面的鍵值對必須和UserMapper.xml中使用的變量對應!!!

對象傳遞參數,直接在sql中去對象的屬性。

隻有一個基本資料類型參數的情況下,可以直接在sql中使用

多個參數用map或注解!

8.模糊查詢

1.java執行的時候傳遞通配符%

List<User> users = mapper.likeUser("%李%");      

2.在sql拼接中使用通配符

<select id="likeUser" resultType="com.liu.Pojo.User">
    select * from user where name like "%"#{name}"%"
</select>      

第二種寫法:

<select id="queryAll" resultMap="USER" parameterType="map">
    select * from user
    <where>
        <if test="name!=null">
            name like '%${name}%'
        </if>
    </where>
</select>      

4.XML配置

1.核心配置檔案

mybaits-config,xml

  • properties(屬性)
  • settings(設定)
  • typeAliases(類型别名)
  • typeHandlers(類型處理器)
  • objectFactory(對象工廠)
  • plugins(插件)
  • environments(環境配置)
    • environment(環境變量)
      • transactionManager(事務管理器)
      • dataSource(資料源)
  • databaseIdProvider(資料庫廠商辨別)
  • mappers(映射器)

2.環境配置

Mybatis可以配置成适應多環境

注:盡管可以配置多個環境,但是每個sqlSessionFactory執行個體隻能選擇一種環境

學會使用配置多套運作環境!

Mybatis預設的事務管理器就是JDBC,連接配接池:POOLED

3.屬性(properties)

通過propertis來引入配置檔案

1.編寫一個配置檔案:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///mybatis
username=root
password=123456      

2.在核心配置檔案中引入:在核心配置檔案中所有的标簽都有規定的先後順序

資源在核心配置同一個路徑下可以使用相對路徑定位

沒有添加額外參數
<properties resource="db.properties"/>
​
添加額外參數
<properties resource="db.properties">
        <property name="username" value="root1"/>
        <property name="password" value="123456"/>
    </properties>      
  • 可以直接引入配置檔案
  • 可以在其中增加一些配置屬性
  • 如果兩種方式有相同的屬性,優先使用外部配置檔案的屬性!!!

4.類型别名(typeAliases)

類型别名可為 Java 類型設定一個縮寫名字。 它僅用于 XML 配置,意在降低備援的全限定類名書寫

第一種方式:

<typeAliases>
        <typeAlias type="com.liu.Pojo.User" alias="User"/>
    </typeAliases>      

第二種方式

可以指定一個包名,Mybatis會在這個包名下面搜尋需要的JavaBean,比如:

掃描的實體類的名稱,它的預設别名就是這個類的首字母小寫。

<typeAliases>
            <package name="com.liu.Pojo"/>
        </typeAliases>x      

在實體類比較少的情況使用第一種,

如果實體類十分多的時候,建議第二種

第一種可以DIY别名,第二種不行。如果非要在實體類上增加注解,注解方式大于預設搜尋

@Alias("hello")
public class User(){};      

5.映射器(mappers)

MapperRegistry:注冊綁定我們需要的Mapper檔案

方式一:【推薦使用】

<mappers>
        <mapper resource="com/liu/Mapper/UserMapper.xml"/>
    </mappers>      

方式二:使用class方式綁定注冊

<mappers>
        <mapper class="com.liu.Mapper.UserMapper"/>
    </mappers>      

方式三:使用包掃描注冊綁定

<mappers>
        <package name="com.liu.Mapper"/>
    </mappers>      

方式二和方式三注意!!:

  • 接口和它的Mapper配置檔案必須同名
  • 接口和它的Mapper配置檔案必須在同一個包下面

6.生命周期

mybaties學習筆記Junit1.簡介2.第一個mybatis程式3.CRUD4.XML配置5.解決屬性名和字段名不一緻的問題6.日志7.分頁8.使用注解開發9.Lombok10.多對一11.一對多12.動态SQL6.foreach(幾乎不用)7.SQL片段13.緩存(了解)14.Mybatis緩存Mybatis注意點

生命周期類和作用域是至關重要的,因為錯誤的使用會導緻非常嚴重的并發問題。

SqlSessionFactoryBuilder:

  • 一旦建立了SqlSessionFactory就不在需要他了
  • 局部變量

SqlSessionFactory:

  • 可以想象為資料庫連接配接池
  • SqlSessionFactory 一旦被建立就應該在應用的運作期間一直存在,沒有任何理由丢棄它或重新建立另一個執行個體。
  • 是以 SqlSessionFactory 的最佳作用域是應用作用域。(程式開始他就開始,程式結束他就結束)
  • 簡單的就是使用單例模式或者靜态單例模式。

SqlSession:

  • 連接配接到連接配接池的一個請求!
  • SqlSession 的執行個體不是線程安全的,是以是不能被共享的,是以它的最佳的作用域是請求或方法作用域
  • 用完之後趕緊關閉,否則資源被占用
mybaties學習筆記Junit1.簡介2.第一個mybatis程式3.CRUD4.XML配置5.解決屬性名和字段名不一緻的問題6.日志7.分頁8.使用注解開發9.Lombok10.多對一11.一對多12.動态SQL6.foreach(幾乎不用)7.SQL片段13.緩存(了解)14.Mybatis緩存Mybatis注意點

每一個Mapper代表一個具體的業務。

5.解決屬性名和字段名不一緻的問題

解決方法:

  • 起别名
<select id="getUserById" parameterType="int" resultType="com.liu.Pojo.User">
        select id,name,password as pwd from user where  id = #{id}
    </select>      

2.resultMap

結果集映射

id name password
id name pwd      

resultMap

元素是 MyBatis 中最重要最強大的元素。它可以讓你從 90% 的 JDBC

ResultSets

資料提取代碼中解放出來,并在一些情形下允許你進行一些 JDBC 不支援的操作。

ResultMap 的設計思想是,對簡單的語句做到零配置,對于複雜一點的語句,隻需要描述語句之間的關系就行了。

<!--   resultMap就是使用這裡的id,類型映射為實體類 -->
    <resultMap id="UserMap" type="User">
<!--       property表示實體類屬性,column表示資料庫字段映射。将字段映射為實體類的對應屬性 -->
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="pwd" column="password"/>  
    </resultMap>
    <select id="getUserList" resultMap="UserMap">
    select * from user
  </select>
      

6.日志

6.1日志工廠

如果一個資料庫操作出現了異常,我們需要排錯。日志就是我們最好的助手。

曾經:sout、debug

現在:日志工廠!

mybaties學習筆記Junit1.簡介2.第一個mybatis程式3.CRUD4.XML配置5.解決屬性名和字段名不一緻的問題6.日志7.分頁8.使用注解開發9.Lombok10.多對一11.一對多12.動态SQL6.foreach(幾乎不用)7.SQL片段13.緩存(了解)14.Mybatis緩存Mybatis注意點
  • SLF4J
  • LOG4J【掌握】
  • LOG4J2
  • JDK_LOGGING
  • COMMONS_LOGGING
  • STDOUT_LOGGING【掌握】
  • NO_LOGGING

在Mybatis中具體使用哪一個日志實作,在設定中設定!

STDOUT_LOGGING:标準日志輸出

配置設定的時候一定要注意格式、大小寫、空格等問題

<settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>      

6.2Log4j

Apache的開源項目log4j是一個功能強大的日志元件,提供友善的日志記錄。

  • 日志可以輸出到控制到或GUI元件
  • 我們可以控制每一條日志輸出的格式
  • 通過設定每一條日志的級别,我們能夠更細緻的控制日志生成的過程。
  • 通過配置檔案來進行配置,不需要我們修改應用的代碼

1.導入LOG4J的包

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>      

2.log4j.properties

### 配置根 ###
#配置日志類型
log4j.rootLogger = debug,console ,file

### 設定輸出sql的級别,其中logger後面的内容全部為jar包中所包含的包名 ###
log4j.logger.org.apache=debug
log4j.logger.java.sql.Connection=debug
log4j.logger.java.sql.Statement=debug
log4j.logger.java.sql.PreparedStatement=debug
log4j.logger.java.sql.ResultSet=debug

### 配置輸出到控制台 ###
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern =  %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n

### 配置輸出到檔案 ###
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File = ./logs/mybatis.log
log4j.appender.file.Append = true
log4j.appender.file.Threshold = DEBUG
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 配置輸出到檔案,并且每天都建立一個檔案 ###
log4j.appender.dailyRollingFile = org.apache.log4j.DailyRollingFileAppender
log4j.appender.dailyRollingFile.File = logs/log.log
log4j.appender.dailyRollingFile.Append = true
log4j.appender.dailyRollingFile.Threshold = DEBUG
log4j.appender.dailyRollingFile.layout = org.apache.log4j.PatternLayout
log4j.appender.dailyRollingFile.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

#日志輸出級别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
#log4j.logger.java.sql.Statement=DEBUG
#log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PraparedStatement=DEBUG      

3.配置log4j為日志的實作

<settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>      

4.Log4j的使用,直接測試運作查詢就行了

簡單使用

1.在需要使用log4j的類中,導入包,包不要導錯了,需要導入apeach的log4j

2.生成日志對象,加載參數為目前類的class

static Logger logger = Logger.getLogger(mybatistest.class);      

3.日志級别

logger.info("info:進入testlog4j");
logger.debug("debug:進入testlog4j");
logger.error("error:進入testlog4j");      

7.分頁

為什麼要分頁?

  • 減少資料的處理量

#{參數名}:按照preparedstatement解析sql語句時所使用的的?占位符

${參數名}:傳什麼參數,就按字元串拼接方式進行填充

7.1使用limit分頁,文法:

select * from user limit statIndex,pagesize;

select * from user limit 2,5
select * from user limit 3      

使用mybatis實作分頁,核心SQl

1.接口

//分頁查詢
public List<User> limitUser(Map<String,Integer> map);      

2.Mapper.xml

<!--    實作分頁查詢-->
    <select id="limitUser" parameterType="map" resultType="user">
        select * from user limit #{startIndex},#{pageSize}
    </select>      

3.測試

//分頁查詢
@Test
public void limitUser(){
    SqlSession sqlSession = MybatisUtil.getsqlSession();

    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    HashMap<String, Integer> map = new HashMap<String, Integer>();
    map.put("startIndex",0);
    map.put("pageSize",3);
    List<User> users = mapper.limitUser(map);
    for (User user : users) {
        System.out.println(user);
    }
}      

7.2useGeneratedKeys

如果想要拿到插入資料後自動遞增的主鍵值時,使用useGeneratedKeys=true

KeyColumn:指定自動遞增的列明

KeyProperty:指定傳入的參數對象中用于存放自動遞增的值對應的屬性

8.使用注解開發

8.1面向接口程式設計

  • 接口定義與實作的分離
  • 接口的本身反應了系統設計人員對系統的抽象了解
  • 接口也應有兩個類:
    • 一個是對一個個體的抽象abstract
    • 一個是對個體某個方面的抽象interface

8.2使用注解開發

1.注解直接在接口上實作

@Select("select * from user")
List<User> getUsers();      

2.需要在核心配置檔案中綁定接口!

<mappers>
    <mapper class="com.liu.Mapper.UserMapper2"/>
</mappers>      

3.測試

//注解方式
@Test
public void zjUsers(){
    SqlSession sqlSession = MybatisUtil.getsqlSession();

    UserMapper2 mapper = sqlSession.getMapper(UserMapper2.class);
    List<User> users = mapper.getUsers();
    for (User user : users) {
        System.out.println(user);
    }

    sqlSession.close();
}      

本質:反射機制實作

底層:動态代理

8.3CRUD

我們可以在工具類建立的時候實作自動送出事務!

return sqlSessionFactory.openSession(true);      

編寫接口,增加注解

//方法存在多個參數時,所有的參數前面必須加上@Param("id")注解
    @Select("select * from user where id=#{id} and name=#{name}")
    public User getUserById(@Param("id") int id,@Param("name") String username);

    @Insert("insert into user values (#{id},#{name},#{password})")
    public int addUser(User user);

    @Update("update user set name=#{name},password=#{password} where id=#{id}")
    int UpdateUser(User user);

    @Delete("delete from user where id=#{id}")
    public int delUser(@Param("id") int pid);      

【我們必須将接口綁定到注冊到我們的核心配置檔案中】

<mappers>
        <package name="com.liu.Mapper"/>
    </mappers>      

關于@Param(")注解

  • 基本類型的參數或則String類型的參數需要加上
  • 引用資料類型不需要加
  • 如果隻有一個資料類型的話可以忽略,建議也加上
  • 我們在SQL中引用的就是我們這裡的@Param設定的屬性名

#{}和${}差別:

  • #{}和${}這兩個文法是為了動态傳遞參數而存在的,是Mybatis實作動态SQL的基礎
  • #{} 是 占位符 :動态解析 -> 預編譯 -> 執行
  • ${} 是 拼接符 **:動态解析 -> 編譯 -> 執行

類似statement和preparestatement

9.Lombok

  • java library
  • plugs
  • build tools

使用步驟:

1.在IDEA安裝plug,Lombok插件

2.在maven中導入Lombok依賴

<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>      

@Data:,toString,GetandSet,hashcode,equals

@AllArgsConstructor
@NoArgsConstructor      

全參構造和無參構造

3.在實體類上加注解即可

10.多對一

  • 對學生來說,關聯,多個學生關聯一個老師【多對一】
  • 對老師而言,集合,一個老師輔導多個學生【一對多】

環境搭建:

1.導入Lombok

2.建立實體類Teacher,Student

3.建立Mapper接口

4.建立Mapper.xml檔案

5.在核心配合檔案中綁定Mapper接口或檔案

6.測試

需求查詢所有的學生資訊以及對應的老師資訊。

1.按照查詢嵌套處理

<!--    使用結果集映射需要使用resultMap-->
<select id="getStudent" resultMap="StudentTeacher">
    select * from student
</select>
<resultMap id="StudentTeacher" type="student">
    <!--        複雜的屬性,我們需要單獨處理-->
    <!--        對象使用association-->
    <result property="id" column="id"/>
    <result property="name" column="name"/>
    <association property="teacher" column="id" javaType="Teacher" select="getTeacher"/>
    <!--        集合使用collection-->
    <!--        <collection property=""-->
</resultMap>

<select id="getTeacher" resultType="teacher">
    select * from teacher where id=#{id}
</select>      
mybaties學習筆記Junit1.簡介2.第一個mybatis程式3.CRUD4.XML配置5.解決屬性名和字段名不一緻的問題6.日志7.分頁8.使用注解開發9.Lombok10.多對一11.一對多12.動态SQL6.foreach(幾乎不用)7.SQL片段13.緩存(了解)14.Mybatis緩存Mybatis注意點

第二條select語句中的where裡面的條件#{},花括号裡面随便寫都不會影響查詢結果

2.按照結果嵌套處理

<!--    按照結果嵌套處理-->
<select id="getStudent2" resultMap="StudentTeacher2">
    select s.id  sid,s.name  sname,t.name  tname
    from student as s,teacher as t where s.id=t.id
</select>

<resultMap id="StudentTeacher2" type="student">
    <result column="sid" property="id"/>
    <result column="sname" property="name"/>
    <association property="teacher" javaType="Teacher">
        <result property="tid" column="id"/>
        <result property="name" column="tname"/>
    </association>
</resultMap>      

查詢結果:

Student(id=1, name=liulang, cno=1, teacher=Teacher(id=1, name=chentao, cno=1)) Student(id=2, name=lixiaosheng, cno=1, teacher=Teacher(id=1, name=chentao, cno=1)) Student(id=3, name=zhenghaiqing, cno=1, teacher=Teacher(id=1, name=chentao, cno=1))

11.一對多

一個老師擁有多個學生

1.結果集映射

<select id="getTeacher2" resultMap="TeacherStudent">
    select s.id sid,s.name sname,t.name tname,t.id tid,t.cno tcno,s.cno scno
    from student s,teacher t where s.cno=t.cno
</select>
<resultMap id="TeacherStudent" type="teacher">
    <result property="id" column="tid"/>
    <result property="cno" column="tcno"/>
    <result property="name" column="tname"/>
    <collection property="students" ofType="student">
        <result property="id" column="sid"/>
        <result property="cno" column="scno"/>
        <result property="name" column="sname"/>
    </collection>
</resultMap>      

2.子查詢方式

<!--    子查詢-->
    <select id="getTeacher" resultMap="TeacherStudent1">
        select * from teacher
    </select>
    <resultMap id="TeacherStudent1" type="Teacher">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="cno" column="cno"/>
<!--      column使用者傳遞給子查詢作為where條件  -->
        <collection property="students" column="cno" javaType="ArrayList" ofType="Student" select="getStudent"/>
    </resultMap>
    <select id="getStudent" resultType="Student">
        select * from student where cno=#{cno}
    </select>      

查詢結果:

Teacher(id=1, name=chentao, cno=1, students=[Student(id=1, name=liulang, cno=1), Student(id=2, name=lixiaosheng, cno=1), Student(id=3, name=zhenghaiqing, cno=1)])

總結:

1.關聯-association【多對一】

2.集合-collection【一對多】

3.javaType & ofType

1.javaType用來指定實體類中屬性的類型

2.ofTyp用來指定映射到list或則集合中的pojo類型,泛型中的集合類型

注意:

  • 保證SQL的可讀性,盡量保證通俗易懂
  • 注意一對多和多對一中,屬性名和字段的問題
  • 如果問題不好排查,可以使用日志,建立使用log4j

12.動态SQL

什麼是動态SQL:根據不同的條件生成不同的SQL語句

所謂動态SQL:本質還是SQL語句,隻是我們可以再SQL層面,去執行一個邏輯代碼

1.搭建環境

開啟駝峰命名:隻應用于資料庫映射java使用的駝峰命名

<settings>
        <!--        開啟駝峰命名映射-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>      

2.where

where 元素隻會在子元素傳回任何内容的情況下才插入 “WHERE” 子句。而且,若子句的開頭為 “AND” 或 “OR”,where 元素也會将它們去除。

使用where标簽如果你滿足的第一個條件在where 後面添加了一個and,會被這個标簽自動删除and然後正常執行,如果你沒有過濾條件,那麼where标簽會将where字句删除

<where>
    <if test="state != null">
         state = #{state}
    </if>
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>      

3.IF

BlogMapper.xml

<insert id="addBlog" parameterType="blog">
        insert into blog values(#{id},#{title},#{author},#{createTime},#{view});
    </insert>

    <select id="queryBlogIf" parameterType="map" resultType="blog">
        select * from blog where 1=1
        <if test="title != null">
           and title=#{title}
        </if>
        <if test="author != null">
             and author = #{author}
        </if>
    </select>      

test:

public void queryBlogIf(){
       SqlSession sqlSession = MybatisUtil.getsqlSession();

       BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
       HashMap map = new HashMap();
       map.put("title","Mybatis");
//       map.put("author","ll");
       List<Blog> blogs = mapper.queryBlogIf(map);
       for (Blog item : blogs) {
           System.out.println(item);
       }

       sqlSession.close();
   }      

4.choose(swtich)

<select id="queryBlogChoose" resultType="blog" parameterType="map">
        select * from blog
        <where>
            <choose>
                <when test="title != null">
                    title=#{title}
                </when>
                 <when test="author != null">
                     author=#{author}
                </when>
                <otherwise>
                    view > 0
                </otherwise>
            </choose>

        </where>
    </select>      

作用:和java的swtich功能類似

  • 隻會滿足其中之一,如果存在滿足多個條件的話也隻會滿足第一個條件

5.Set

作用:set 元素會動态地在行首插入 SET 關鍵字,并會删掉額外的逗号```xml

<update id="updateBlogSet" parameterType="map" >
    update blog
    <set>
        <if test="title != null">
            title=#{title},
        </if>
        <if test="author != null">
            author=#{author},
        </if>
        <if test="view != null">
            view=#{view},
        </if>
    </set>
    where id = '35a166859fb84884b1e18732a05516ff'
</update>      

6.foreach(幾乎不用)

mybaties學習筆記Junit1.簡介2.第一個mybatis程式3.CRUD4.XML配置5.解決屬性名和字段名不一緻的問題6.日志7.分頁8.使用注解開發9.Lombok10.多對一11.一對多12.動态SQL6.foreach(幾乎不用)7.SQL片段13.緩存(了解)14.Mybatis緩存Mybatis注意點

我們想查出資料庫前兩條資料

<select id="queryfreeBlog" resultType="Blog">
        select * from Blog
        <where>
            <foreach collection="list" item="id" open="and (" close=")" separator="or">
                id = #{id}
            </foreach>
        </where>
    </select>      

open:循環開始之前拼接的内容;

close結:循環結束拼接的内容

separator:指定循環中的分隔符

collection:循環周遊的内容

item:周遊的單個變量,在标簽體重來使用

@Test
    public void queryfreeBlog(){
       SqlSession sqlSession = MybatisUtil.getsqlSession();

       BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
       HashMap map = new HashMap();
       ArrayList<String> str = new ArrayList<String>();
       str.add("35a166859fb84884b1e18732a05516ff");
       str.add("6d5cb2ff745c4f658eefd4b21add44f9");
       map.put("list",str);
       List<Blog> blogs = mapper.queryfreeBlog(map);
       for (Blog blog : blogs) {
           System.out.println(blog);
       }

       sqlSession.close();
   }      

結果:

Blog{id='35a166859fb84884b1e18732a05516ff', title='這不是結局', author='小新', createTime=2021-07-29, view=998} Blog{id='6d5cb2ff745c4f658eefd4b21add44f9', title='java', author='劉星', createTime=2021-07-29, view=1005}

注意:

如果這裡我們沒有傳遞任何參數,就會自動删除where條件,将會查出所有資訊

7.SQL片段

有的時候,我們可能會将一些功能的部分抽取出來,友善複用

<sql id="if-author-title">
        <if test="title != null">
            and title=#{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </sql>
    <select id="queryBlogIf" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <include refid="if-author-title"/>
        </where>
    </select>      

實作代碼的複用

使用sql标簽提取公共部分

在使用的地方用include标簽引入SQL片段通過id引入

注意:

  • 最好基于單表來定義SQL片段
  • 不要存在where标簽
  • 最好隻要一些IF判斷就好了

13.緩存(了解)

1.什麼是緩存?

  • 存在記憶體中的臨時資料
  • 将使用者資料查詢到的資料放在緩存中,使用者去查詢資料就不用從磁盤上查詢,從緩存中讀取,進而提高效率,解決了高并發系統的性能問題

2.為什麼要使用緩存?

  • 減少和資料庫的互動次數,減少系統開銷,提高系統效率

3.什麼樣的資料能使用緩存?

查詢:連接配接資料庫,耗記憶體

解決:一次查詢的結果,給他暫存在一個可以直接讀取的地方--》記憶體:緩存

我們再次查詢相同資料的時候我們走緩存,就不用走資料庫了。

14.Mybatis緩存

  • Mybatis包含一個非常強大的查詢緩存特性,它可以非常友善的定制和配置緩存,緩存可以極大地提升查詢效率
  • Mybatis系統中預設定義了兩級緩存:一級緩存和二級緩存
  • 預設情況下,隻有一級緩存開啟。(本地緩存)
  • 二級緩存需要手動開啟和配置,他是基于namespace級别的緩存
  • 為了提高擴充性,mybatis定了緩存接口Cache,我們可以通過實作Cache接口來定義二級緩存

一級緩存

  • 一級緩存也叫本地緩存
  • 與資料庫同義詞會話期間查詢到的資料會被放在本地緩存中
  • 以後如果需要擷取相同的資料的話,直接從緩存中拿,沒有必要在去查資料庫

實驗步驟

1.開啟日志

2.測試在一個Session中查詢兩次相同的記錄

3.檢視日志輸出

@Test
    public void queryAllUser(){
        SqlSession sqlSession = MybatisUtil.getsqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = mapper.queryAllUser(6);
        System.out.println(users);

        System.out.println("=============================================");
        List<User> users1 = mapper.queryAllUser(6);
        System.out.println(users1);
        System.out.println(users==users1);


        sqlSession.close();
    }      
mybaties學習筆記Junit1.簡介2.第一個mybatis程式3.CRUD4.XML配置5.解決屬性名和字段名不一緻的問題6.日志7.分頁8.使用注解開發9.Lombok10.多對一11.一對多12.動态SQL6.foreach(幾乎不用)7.SQL片段13.緩存(了解)14.Mybatis緩存Mybatis注意點

增删改會重新整理原來的東西

mybaties學習筆記Junit1.簡介2.第一個mybatis程式3.CRUD4.XML配置5.解決屬性名和字段名不一緻的問題6.日志7.分頁8.使用注解開發9.Lombok10.多對一11.一對多12.動态SQL6.foreach(幾乎不用)7.SQL片段13.緩存(了解)14.Mybatis緩存Mybatis注意點

緩存失效的情況:

  • 增删改都有可能改變原來的資料,必定會重新整理緩存
  • 查詢不同的Mapper.xml
  • 手動清理緩存
  • 查詢不同的東西

小結:一級緩存預設是開啟的,隻在一次SqlSessionFactory中有效,也就是拿到連結到關閉連接配接區間有效。一級緩存也是無法關閉的。

一級緩存作用域就是sqlsession對象,存儲的内容,查詢後的結果集,在sqlSession對象中有Map結果,Map的值就是結果集的對象。

二級緩存

  • 二級緩存也叫全局緩存,一級緩存作用域太低了,是以誕生了二級緩存
  • 基于namespace級别的緩存,一個名稱空間,對應一個二級緩存
  • 工作機制:
    • 一個會話查詢一條資料,這個資料就會被放在目前會話的一級緩存中
    • 如果目前會話關閉了,這個會話對應的一級緩存就沒有了;但是我們想要的是,會話關閉了,一級緩存中的資料會被儲存到二級緩存中
    • 新的會話查詢資訊,就可以從二級緩存中擷取内容;

預設情況下,隻啟用了本地的會話緩存,它僅僅對一個會話中的資料進行緩存。 要啟用全局的二級緩存,隻需要在你的 SQL 映射檔案中添加一行:<cache/>

步驟:

1.開啟緩存設定

<setting name="cacheEnabled" value="true"/>      

2.要是用二級緩存需要在Mapper中開啟

<!--在目前的xml中開啟二級緩存-->
    <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>      

也可以自定義一些參數

3.測試

@Test
    public void queryAllUser(){
        SqlSession sqlSession1 = MybatisUtil.getsqlSession();
        SqlSession sqlSession2 = MybatisUtil.getsqlSession();
        UserMapper mapper = sqlSession1.getMapper(UserMapper.class);
        List<User> users = mapper.queryAllUser(6);
        System.out.println(users);
        sqlSession1.close();



        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
        List<User> users2 = mapper2.queryAllUser(6);
        System.out.println(users2);

        sqlSession2.close();
    }      
mybaties學習筆記Junit1.簡介2.第一個mybatis程式3.CRUD4.XML配置5.解決屬性名和字段名不一緻的問題6.日志7.分頁8.使用注解開發9.Lombok10.多對一11.一對多12.動态SQL6.foreach(幾乎不用)7.SQL片段13.緩存(了解)14.Mybatis緩存Mybatis注意點

隻進行了一次查詢

小結:二級緩存隻能在一個namespace内有效,也就是隻在一個xml檔案内。所有的資料都會先放在一級緩存中,隻有當會話送出或關閉的時候轉存到二級緩存

問題!:我們需要将實體類序列化

implements Serializable      

查找順序

mybaties學習筆記Junit1.簡介2.第一個mybatis程式3.CRUD4.XML配置5.解決屬性名和字段名不一緻的問題6.日志7.分頁8.使用注解開發9.Lombok10.多對一11.一對多12.動态SQL6.foreach(幾乎不用)7.SQL片段13.緩存(了解)14.Mybatis緩存Mybatis注意點

自定義緩存--ehcache

ehcache是一種廣發使用的開源java分布式緩存

Mybatis注意點

mybatis-config.xml:

mybaties學習筆記Junit1.簡介2.第一個mybatis程式3.CRUD4.XML配置5.解決屬性名和字段名不一緻的問題6.日志7.分頁8.使用注解開發9.Lombok10.多對一11.一對多12.動态SQL6.foreach(幾乎不用)7.SQL片段13.緩存(了解)14.Mybatis緩存Mybatis注意點

MybatisUtil.java

mybaties學習筆記Junit1.簡介2.第一個mybatis程式3.CRUD4.XML配置5.解決屬性名和字段名不一緻的問題6.日志7.分頁8.使用注解開發9.Lombok10.多對一11.一對多12.動态SQL6.foreach(幾乎不用)7.SQL片段13.緩存(了解)14.Mybatis緩存Mybatis注意點

UserMapper.xml

mybaties學習筆記Junit1.簡介2.第一個mybatis程式3.CRUD4.XML配置5.解決屬性名和字段名不一緻的問題6.日志7.分頁8.使用注解開發9.Lombok10.多對一11.一對多12.動态SQL6.foreach(幾乎不用)7.SQL片段13.緩存(了解)14.Mybatis緩存Mybatis注意點