狂神說Java Mybatis筆記


參考:https://blog.csdn.net/ddddeng_/article/details/106927021

MyBatis
1、簡介
1.1 什么是Mybatis

MyBatis 是一款優秀的持久層框架;它支持自定義 SQL、存儲過程以及高級映射。MyBatis 免除了幾乎所有的 JDBC 代碼以及設置參數和獲取結果集的工作。

MyBatis 可以通過簡單的 XML 或注解來配置和映射原始類型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 對象)為數據庫中的記錄。

1.2 持久化 

持久化就是將程序的數據在持久狀態和瞬時狀態轉化的過程。

內存:斷電即失。數據庫(Jdbc),io文件持久化。

為什么要持久化?

有一些對象,不能讓他丟掉。內存太貴

1.3 持久層
Dao層、Service層、Controller層

完成持久化工作的代碼塊
層界限十分明顯
1.4 為什么需要MyBatis
幫助程序員將數據存入到數據庫中,方便,傳統的JDBC代碼太復雜了,簡化,框架,自動化,不用MyBatis也可以,技術沒有高低之分

優點:

簡單易學,靈活

sql和代碼的分離,提高了可維護性。
提供映射標簽,支持對象與數據庫的orm字段關系映射
提供對象關系映射標簽,支持對象關系組建維護
提供xml標簽,支持編寫動態sql
2、第一個Mybatis程序
思路:搭建環境 --> 導入MyBatis --> 編寫代碼 --> 測試

2.1 搭建環境
新建項目

創建一個普通的maven項目

刪除src目錄 (就可以把此工程當做父工程了,然后創建子工程)

導入maven依賴

<!--導入依賴-->

<dependencies>
<!--mysqlq驅動-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.12</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>

 

一般情況下,我們用到的資源文件(各種xml,properites,xsd文件等)都放在src/main/resources下面,利用maven打包時,maven能把這些資源文件打包到相應的jar或者war里。

 

有時候,比如mybatis的mapper.xml文件,我們習慣把它和Mapper.java放一起,都在src/main/java下面,這樣利用maven打包時,就需要修改pom.xml文件,來把mapper.xml文件一起打包進jar或者war里了,否則,這些文件不會被打包的。(maven認為src/main/java只是java的源代碼路徑)。


添加build

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    <ild>

 


創建一個Module

2.2 創建一個模塊(可能會報中文的錯誤,把utf-8改為utf8)
編寫mybatis的核心配置文件(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核心配置文件-->
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?userSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
</configuration>

 


編寫mybatis工具類

//sqlSessionFactory --> sqlSession
public class MybatisUtils {

static SqlSessionFactory sqlSessionFactory = null;

static {
try {
//使用Mybatis第一步 :獲取sqlSessionFactory對象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}

//既然有了 SqlSessionFactory,顧名思義,我們可以從中獲得 SqlSession 的實例.
// SqlSession 提供了在數據庫執行 SQL 命令所需的所有方法。
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}

 


2.3 編寫代碼
實體類

Dao接口

public interface UserDao {
public List<User> getUserList();
}

接口實現類 (由原來的UserDaoImpl轉變為一個Mapper配置文件)

<?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=綁定一個指定的Dao/Mapper接口-->
<mapper namespace="com.kuang.dao.UserDao">
<select id="getUserList" resultType="com.kuang.pojo.User">
select * from USER
</select>
</mapper>

編寫實體類

package com.bupt.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class User {
    private int id;
    private String username;

}

 

測試

import com.bupt.dao.UserDao;
import com.bupt.pojo.User;
import com.bupt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;

public class test {
    @Test
    public void test01(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        User userById = mapper.getUserById(1);
        System.out.println(userById);
        sqlSession.close();
    }

    //增刪改必須提交事務
    @Test
    public void testInsert(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        int i = mapper.addUser(new User(2, "梨花"));
        if(i > 0){
            System.out.println("插入成功");
        }
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void updateUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        mapper.updateUser(new User(2,"劉雷"));
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void testDelete(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        int i = mapper.deleteUser(30);
        sqlSession.commit();
        sqlSession.close();
    }
//實現模糊查詢
    @Test
    public void testLike(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        List<User> userLike = mapper.getUserLike("%張%");
        for (User user:userLike){
            System.out.println(user);
        }
        sqlSession.close();
    }

    @Test
    public void testLike1(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        List<User> zhang = mapper.getUserLike1("張");
        for (User user:zhang){
            System.out.println(user);
        }
        sqlSession.close();
    }

    @Test
    public void testMap(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        HashMap<String, Object> map = new HashMap<>();
        map.put("id",4);
        map.put("username","王虎");
        map.put("birthday","2021-03-27");
        map.put("sex",1);
        map.put("address","北京");
        int i = mapper.insertUser(map);
        sqlSession.commit();
        sqlSession.close();
    }
}
View Code

 

注意點:

org.apache.ibatis.binding.BindingException: Type interface com.kuang.dao.UserDao is not known to the MapperRegistry.

MapperRegistry是什么?

核心配置文件中注冊mappers

 

junit測試

@Test
public void test(){

//1.獲取SqlSession對象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//2.執行SQL
// 方式一:getMapper
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> userList = userDao.getUserList();
for (User user : userList) {
System.out.println(user);
}

//關閉sqlSession
sqlSession.close();
}
View Code

 

可能會遇到的問題:

  • 配置文件沒有注冊
  • 綁定接口錯誤
  • 方法名不對
  • 返回類型不對
  • Maven導出資源問題

3、CURD
1. namespace
namespace中的包名要和Dao/Mapper接口的包名一致

2. select
選擇,查詢語句;

id:就是對應的namespace中的方法名;

resultType : Sql語句執行的返回值;

parameterType : 參數類型;

編寫接口

public interface UserMapper {
//查詢所有用戶
public List<User> getUserList();
//插入用戶
public void addUser(User user);
}

 


編寫對應的mapper中的sql語句

<insert id="addUser" parameterType="com.kuang.pojo.User">
insert into user (id,name,password) values (#{id}, #{name}, #{password})
</insert>

 


測試

@Test
public void test2() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User(3,"黑子","666");
mapper.addUser(user);
//增刪改一定要提交事務
sqlSession.commit();

//關閉sqlSession
sqlSession.close();
}

 


注意:增刪改查一定要提交事務:

sqlSession.commit();
增刪改查全部流程實現

配置依賴和讓資源文件能不導出

 <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.4</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
            </resource>

            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
            </resource>
        </resources>
    </build>
View Code

db.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/student?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username=root
password=root

mybatis-config.xml進行核心配置

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE configuration
 3         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4         "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5 <!--configuration核心配置文件-->
 6 <configuration>
 7     <properties resource="db.properties"/>
 8     <environments default="development">
 9         <environment id="development">
10             <transactionManager type="JDBC"/>
11             <dataSource type="POOLED">
12                 <property name="driver" value="${driver}"/>
13                 <property name="url" value="${url}"/>
14                 <property name="username" value="${username}"/>
15                 <property name="password" value="${password}"/>
16             </dataSource>
17         </environment>
18     </environments>
19 <mappers>
20     <mapper resource="com/bupt/dao/UserDaoMapper.xml"></mapper>
21 </mappers>
22 </configuration>

配置類MybatisUtils 獲取sqlsession

 1 package com.bupt.utils;
 2 
 3 import org.apache.ibatis.io.Resources;
 4 import org.apache.ibatis.session.SqlSession;
 5 import org.apache.ibatis.session.SqlSessionFactory;
 6 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 7 
 8 import java.io.IOException;
 9 import java.io.InputStream;
10 
11 
12 public class MybatisUtils {
13     static SqlSessionFactory factory = null;
14     static {
15         String resource = "mybatis-config.xml";
16         try {
17             InputStream resourceAsStream = Resources.getResourceAsStream(resource);
18             factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
19 
20         } catch (IOException e) {
21             e.printStackTrace();
22         }
23     }
24     public static SqlSession getSqlSession(){
25         return factory.openSession();
26     }
27 }
View Code

實體類(默認和數據庫對應)

 1 package com.bupt.pojo;
 2 
 3 import lombok.AllArgsConstructor;
 4 import lombok.Data;
 5 
 6 @Data
 7 @AllArgsConstructor
 8 public class User {
 9     private int id;
10     private String username;
11 
12 }
View Code

增刪改查的接口UserDao

 1 package com.bupt.dao;
 2 
 3 import com.bupt.pojo.User;
 4 
 5 import java.util.List;
 6 import java.util.Map;
 7 
 8 public interface UserDao {
 9 
10     //查詢
11     User getUserById(int id);//查詢
12 
13     //insert一個用戶
14     int addUser(User user);
15 
16     //更新一個用戶
17     int updateUser(User user);
18 
19     //刪除
20     int deleteUser(int id);
21 
22     int insertUser(Map<String,Object> map);
23 
24     //模糊查詢
25     List<User> getUserLike(String name);
26     List<User> getUserLike1(String name);
27 }
View Code

增刪改查的具體實現UserDaoMapper.xml

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE mapper
 3         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 4         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 5 <mapper namespace="com.bupt.dao.UserDao">
 6 
 7     <select id="getUserById" resultType="com.bupt.pojo.User" parameterType="int">
 8         select  * from user where id = #{id}
 9     </select>
10 
11 <!--    對象中的屬性可以直接取出來-->
12     <insert id="addUser" parameterType="com.bupt.pojo.User" >
13         insert into user (id, username) values(#{id},#{username});
14     </insert>
15 
16     <update id="updateUser" parameterType="com.bupt.pojo.User">
17         update user set username=#{username} where id=#{id};
18     </update>
19     
20     <delete id="deleteUser" parameterType="int">
21         delete  from user where id=#{id};
22     </delete>
23 
24     <select id="getUserLike" parameterType="String" resultType="com.bupt.pojo.User">
25         select  * from user where username like #{name}
26     </select>
27 
28     <select id="getUserLike1" parameterType="String" resultType="com.bupt.pojo.User">
29         select  * from user where username like "%"#{name}"%"
30     </select>
31 
32     <insert id="insertUser" parameterType="map" >
33         insert into user (id,username,birthday,sex,address) values (#{id},#{username},#{birthday},#{sex},#{address});
34     </insert>
35 
36 </mapper>
View Code

別忘了在mybatis配置文件注冊Mapper

<mappers>
    <mapper resource="com/bupt/dao/UserDaoMapper.xml"></mapper>
</mappers>

進行測試

 1 import com.bupt.dao.UserDao;
 2 import com.bupt.pojo.User;
 3 import com.bupt.utils.MybatisUtils;
 4 import org.apache.ibatis.session.SqlSession;
 5 import org.junit.Test;
 6 
 7 import java.util.HashMap;
 8 import java.util.List;
 9 
10 public class test {
11     @Test
12     public void test01(){
13         SqlSession sqlSession = MybatisUtils.getSqlSession();
14         UserDao mapper = sqlSession.getMapper(UserDao.class);
15         User userById = mapper.getUserById(1);
16         System.out.println(userById);
17         sqlSession.close();
18     }
19 
20     //增刪改必須提交事務
21     @Test
22     public void testInsert(){
23         SqlSession sqlSession = MybatisUtils.getSqlSession();
24         UserDao mapper = sqlSession.getMapper(UserDao.class);
25         int i = mapper.addUser(new User(2, "梨花"));
26         if(i > 0){
27             System.out.println("插入成功");
28         }
29         sqlSession.commit();
30         sqlSession.close();
31     }
32 
33     @Test
34     public void updateUser(){
35         SqlSession sqlSession = MybatisUtils.getSqlSession();
36         UserDao mapper = sqlSession.getMapper(UserDao.class);
37         mapper.updateUser(new User(2,"劉雷"));
38         sqlSession.commit();
39         sqlSession.close();
40     }
41 
42     @Test
43     public void testDelete(){
44         SqlSession sqlSession = MybatisUtils.getSqlSession();
45         UserDao mapper = sqlSession.getMapper(UserDao.class);
46         int i = mapper.deleteUser(30);
47         sqlSession.commit();
48         sqlSession.close();
49     }
50 //實現模糊查詢
51     @Test
52     public void testLike(){
53         SqlSession sqlSession = MybatisUtils.getSqlSession();
54         UserDao mapper = sqlSession.getMapper(UserDao.class);
55         List<User> userLike = mapper.getUserLike("%張%");
56         for (User user:userLike){
57             System.out.println(user);
58         }
59         sqlSession.close();
60     }
61 
62     @Test
63     public void testLike1(){
64         SqlSession sqlSession = MybatisUtils.getSqlSession();
65         UserDao mapper = sqlSession.getMapper(UserDao.class);
66         List<User> zhang = mapper.getUserLike1("張");
67         for (User user:zhang){
68             System.out.println(user);
69         }
70         sqlSession.close();
71     }
72 
73     @Test
74     public void testMap(){
75         SqlSession sqlSession = MybatisUtils.getSqlSession();
76         UserDao mapper = sqlSession.getMapper(UserDao.class);
77         HashMap<String, Object> map = new HashMap<>();
78         map.put("id",4);
79         map.put("username","王虎");
80         map.put("birthday","2021-03-27");
81         map.put("sex",1);
82         map.put("address","北京");
83         int i = mapper.insertUser(map);
84         sqlSession.commit();
85         sqlSession.close();
86     }
87 }
View Code

 

6. 萬能Map
假設,我們的實體類,或者數據庫中的表,字段或者參數過多,我們應該考慮使用Map!

UserMapper接口
//用萬能Map插入用戶

public void addUser2(Map<String,Object> map);

 

UserMapper.xml

<!--對象中的屬性可以直接取出來 傳遞map的key-->
<insert id="addUser2" parameterType="map">
insert into user (id,name,password) values (#{userid},#{username},#{userpassword})
</insert>


測試

 1 @Test
 2 public void test3(){
 3 SqlSession sqlSession = MybatisUtils.getSqlSession();
 4 UserMapper mapper = sqlSession.getMapper(UserMapper.class);
 5 HashMap<String, Object> map = new HashMap<String, Object>();
 6 map.put("userid",4);
 7 map.put("username","王虎");
 8 map.put("userpassword",789);
 9 mapper.addUser2(map);
10 //提交事務
11 sqlSession.commit();
12 //關閉資源
13 sqlSession.close();
14 }
View Code

 

  • Map傳遞參數,直接在sql中取出key即可! 【parameter=“map”】
  • 對象傳遞參數,直接在sql中取出對象的屬性即可! 【parameter=“Object”】
  • 只有一個基本類型參數的情況下,可以直接在sql中取到
  • 多個參數用Map , 或者注解!

7. 模糊查詢
模糊查詢這么寫?

Java代碼執行的時候,傳遞通配符% %

    <select id="getUserLike1" parameterType="String" resultType="com.bupt.pojo.User">
        select  * from user where username like #{name}
    </select>

 

 1 List<User> userList = mapper.getUserLike("%李%"); 
在sql拼接中使用通配符

 1 <select id="getUserList2" resultType="com.bupt.pojo.User"> 2 select * from user where name like "%"#{name}"%" 3 </select> 


目前程序的框架為

 

 

 pom.xml

 1 <?xml version="1.0" encoding="UTF8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6 
 7     <groupId>org.example</groupId>
 8     <artifactId>Mybatis</artifactId>
 9     <packaging>pom</packaging>
10     <version>1.0-SNAPSHOT</version>
11     <modules>
12         <module>mybatis-1-crud</module>
13     </modules>
14     <build>
15         <resources>
16             <resource>
17                 <directory>src/main/java</directory>
18                 <includes>
19                     <include>**/*.properties</include>
20                     <include>**/*.xml</include>
21                 </includes>
22                 <filtering>true</filtering>
23             </resource>
24         </resources>
25     </build>
26     <properties>
27         <maven.compiler.source>8</maven.compiler.source>
28         <maven.compiler.target>8</maven.compiler.target>
29     </properties>
30     <dependencies>
31         <dependency>
32             <groupId>mysql</groupId>
33             <artifactId>mysql-connector-java</artifactId>
34             <version>5.1.48</version>
35         </dependency>
36         <dependency>
37             <groupId>org.mybatis</groupId>
38             <artifactId>mybatis</artifactId>
39             <version>3.5.4</version>
40         </dependency>
41         <!--junit-->
42         <dependency>
43             <groupId>junit</groupId>
44             <artifactId>junit</artifactId>
45             <version>4.12</version>
46             <scope>test</scope>
47         </dependency>
48 
49     </dependencies>
50 
51 </project>
View Code

mybatis-config.xml

<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--configuration核心配置文件-->
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/myschool?userSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/bupt/dao/UserMapper.xml"/>
    </mappers>
</configuration>
View Code

 

實體類User

package com.bupt.pojo;

import org.apache.ibatis.session.SqlSessionFactory;

import java.util.Objects;

public class User {
    private int id;
    private String name;
    private String pwd;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public User(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    public User() {
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return id == user.id && Objects.equals(name, user.name) && Objects.equals(pwd, user.pwd);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name, pwd);
    }
}
View Code

UserDao

package com.bupt.dao;

import com.bupt.pojo.User;

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

public interface UserDao {
    //查詢接口
    List<User> getUserList();

    User getUserById(int id);

    //插入接口
    public void addUser(User user);

    //更新一個用戶
    public void updateUser(User user);

    //刪除一個用戶
    public void deleteUser(int id);

    //插入用戶
    public void addUser2(Map<String, Object> map);

    //模糊查詢用戶
    List<User> getUserList2(String name);

}
View Code

UserMapper.xml

<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--configuration核心配置文件-->
<mapper namespace="com.bupt.dao.UserDao">
    <select id="getUserList" resultType="com.bupt.pojo.User">
        select  * from USER;
    </select>

    <select id="getUserById" parameterType="int" resultType="com.bupt.pojo.User">
        select  * from USER where id=#{id};
    </select>

    <insert id="addUser" parameterType="com.bupt.pojo.User">
        insert into user (id,name,pwd) values (#{id},#{name},#{pwd});
    </insert>

    <update id="updateUser" parameterType="com.bupt.pojo.User">
        update user set name=#{name}, pwd=#{pwd} where id=#{id};
    </update>

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

    <insert id="addUser2" parameterType="map">
        insert  into user(id,name) values(#{userid},#{username})
    </insert>

    <select id="getUserList2"  resultType="com.bupt.pojo.User">
        select * from user where name like "%"#{name}"%"
    </select>
</mapper>
View Code

MybatisUtils

 1 package com.bupt.utils;
 2 
 3 import org.apache.ibatis.io.Resources;
 4 import org.apache.ibatis.session.SqlSession;
 5 import org.apache.ibatis.session.SqlSessionFactory;
 6 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 7 
 8 import java.io.IOException;
 9 import java.io.InputStream;
10 
11 public class MybatisUtils {
12     static  SqlSessionFactory build = null;
13     static {
14         String resources = "mybatis-config.xml";
15         try {
16             InputStream resourceAsStream = Resources.getResourceAsStream(resources);
17             build = new SqlSessionFactoryBuilder().build(resourceAsStream);
18 
19         } catch (IOException e) {
20             e.printStackTrace();
21         }
22     }
23     public static SqlSession getSqlSession(){
24         return build.openSession();
25     }
26 }
View Code

 

經常碰到這樣的面試題目:#{}和${}的區別是什么?
 
網上的答案是:#{}是預編譯處理,$ {}是字符串替換。

mybatis在處理#{}時,會將sql中的#{}替換為?號,調用PreparedStatement的set方法來賦值;

mybatis在處理 $ { } 時,就是把 ${ } 替換成變量的值。

使用 #{} 可以有效的防止SQL注入,提高系統安全性。

sql注入指的是用戶輸入 or 1=1等變量導致原sql語句邏輯發生了變化,使得可以直接進入數據庫,而使用預編譯的方法可以讓sql語句只把傳入的數據當做參數進行處理

而不會改變原有sql的邏輯,preparestatement和#{}都是把變量預編譯,防止sql注入。

 SQL注入詳解 - myseries - 博客園 (cnblogs.com)

4、配置解析

1. 核心配置文件

  • mybatis-config.xml

  • Mybatis的配置文件包含了會深深影響MyBatis行為的設置和屬性信息。

 1 configuration(配置)
 2     properties(屬性)
 3     settings(設置)
 4     typeAliases(類型別名)
 5     typeHandlers(類型處理器)
 6     objectFactory(對象工廠)
 7     plugins(插件)
 8     environments(環境配置)
 9         environment(環境變量)
10             transactionManager(事務管理器)
11             dataSource(數據源)
12     databaseIdProvider(數據庫廠商標識)
13     mappers(映射器)

2. 環境配置 environments
MyBatis 可以配置成適應多種環境

不過要記住:盡管可以配置多個環境,但每個 SqlSessionFactory 實例只能選擇一種環境

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

MyBatis默認的事務管理器就是JDBC ,連接池:POOLED

3. 屬性 properties
我們可以通過properties屬性來實現引用配置文件

這些屬性可以在外部進行配置,並可以進行動態替換。你既可以在典型的 Java 屬性文件中配置這些屬性,也可以在 properties 元素的子元素中設置。【db.poperties】

編寫一個配置文件

db.properties

1 driver=com.mysql.cj.jdbc.Driver
2 url=jdbc:mysql://localhost:3306/mybatis?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
3 username=root
4 password=root

在核心配置文件中引入

<!--引用外部配置文件-->
<properties resource="db.properties">
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</properties>
  • 可以直接引入外部文件
  • 可以在其中增加一些屬性配置
  • 如果兩個文件有同一個字段,優先使用外部配置文件的

類型別名 typeAliases
類型別名可為 Java 類型設置一個縮寫名字。 它僅用於 XML 配置.

意在降低冗余的全限定類名書寫。

<!--可以給實體類起別名-->

<typeAliases>
<typeAlias type="com.kuang.pojo.User" alias="User"/>
</typeAliases>

 



也可以指定一個包,每一個在包 domain.blog 中的 Java Bean,在沒有注解的情況下,會使用 Bean 的首字母小寫的非限定類名來作為它的別名。 比如 domain.blog.Author 的別名為 author,;若有注解,則別名為其注解值。見下面的例子:

<typeAliases>
<package name="com.kuang.pojo"/>
</typeAliases>

 



在實體類比較少的時候,使用第一種方式。

如果實體類十分多,建議用第二種掃描包的方式。

第一種可以DIY別名,第二種不行,如果非要改,需要在實體上增加注解。

@Alias("author")
public class Author {
...
}

 



5. 設置 Settings
這是 MyBatis 中極為重要的調整設置,它們會改變 MyBatis 的運行時行為。

 

6. 其他配置
typeHandlers(類型處理器)
objectFactory(對象工廠)
plugins 插件
mybatis-generator-core
mybatis-plus
通用mapper
7. 映射器 mappers
MapperRegistry:注冊綁定我們的Mapper文件;

方式一:【推薦使用】

<!--每一個Mapper.xml都需要在MyBatis核心配置文件中注冊-->
<mappers>
<mapper resource="com/kuang/dao/UserMapper.xml"/>
</mappers>

 


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

<!--每一個Mapper.xml都需要在MyBatis核心配置文件中注冊-->

<mappers>
<mapper class="com.kuang.dao.UserMapper"/>
</mappers>

 


注意點:

接口和他的Mapper配置文件必須同名
接口和他的Mapper配置文件必須在同一個包下
方式三:使用包掃描進行注入

<mappers>
<package name="com.kuang.dao"/>
</mappers>

 



8. 作用域和生命周期


聲明周期和作用域是至關重要的,因為錯誤的使用會導致非常嚴重的並發問題。

SqlSessionFactoryBuilder:

一旦創建了SqlSessionFactory,就不再需要它了
局部變量
SqlSessionFactory:

說白了就可以想象為:數據庫連接池
SqlSessionFactory一旦被創建就應該在應用的運行期間一直存在,沒有任何理由丟棄它或重新創建一個實例。
因此SqlSessionFactory的最佳作用域是應用作用域(ApplocationContext)。
最簡單的就是使用單例模式或靜態單例模式。
SqlSession:

連接到連接池的一個請求
SqlSession 的實例不是線程安全的,因此是不能被共享的,所以它的最佳的作用域是請求或方法作用域。
用完之后需要趕緊關閉,否則資源被占用!

 

8、使用注解開發
8.1 面向接口開發
三個面向區別

面向對象是指,我們考慮問題時,以對象為單位,考慮它的屬性和方法;
面向過程是指,我們考慮問題時,以一個具體的流程(事務過程)為單位,考慮它的實現;
接口設計與非接口設計是針對復用技術而言的,與面向對象(過程)不是一個問題,更多的體現就是對系統整體的架構;
8.2 使用注解開發
注解在接口上實現

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

需要在核心配置文件中綁定接口

<mappers>
<mapper class="com.kuang.dao.UserMapper"/>
</mappers>

增刪改查

 1 package com.bupt.dao;
 2 
 3 import com.bupt.pojo.User;
 4 import org.apache.ibatis.annotations.*;
 5 
 6 import java.util.List;
 7 import java.util.Map;
 8 
 9 public interface UserDao {
10 
11     User getUserById(int id);
12     List<User> getUserAll(Map<String,Integer> map);
13 
14     @Select("select * from user")
15     List<User> getUsers();
16 
17     @Delete("delete  from user where id=#{uid}")
18     int deleteUser(@Param("uid") int id);
19 
20     @Insert("insert into user(id,username) values(#{id},#{username})")
21     int insertUser(User user);
22 
23     @Update("update user set username=#{username} where id=#{id}")
24     int update(User user);
25 
26 }

對於增刪改需要把opensession的參數設置為true,這樣就等價於commit操作了,否則無法commit,及時寫了commit,

    public static SqlSession getSqlSession(){
        SqlSession sqlSession = build.openSession(true);
        return  sqlSession;
    }
 1 import com.bupt.dao.UserDao;
 2 import com.bupt.pojo.User;
 3 import com.bupt.utils.MybatisUtils;
 4 import javafx.geometry.VPos;
 5 import org.apache.ibatis.session.SqlSession;
 6 import org.junit.Test;
 7 
 8 import java.util.HashMap;
 9 import java.util.List;
10 import java.util.Map;
11 import java.util.logging.Logger;
12 
13 public class TestGetUserById {
14 
15     @Test
16     public void test01(){
17         Logger logger = Logger.getLogger(String.valueOf(UserDao.class));
18         logger.info("info: 測試log4j");
19         SqlSession sqlSession = MybatisUtils.getSqlSession();
20         UserDao mapper = sqlSession.getMapper(UserDao.class);
21         User userById = mapper.getUserById(1);
22         System.out.println(userById);
23         sqlSession.close();
24     }
25 
26     @Test
27     public void test02(){
28         SqlSession sqlSession = MybatisUtils.getSqlSession();
29         UserDao mapper = sqlSession.getMapper(UserDao.class);
30         HashMap<String, Integer> stringHashMap = new HashMap<String, Integer>();
31         stringHashMap.put("startIndex",1);
32         stringHashMap.put("pagesize",2);
33         List<User> userAll = mapper.getUserAll(stringHashMap);
34         for (User user:userAll){
35             System.out.println(user);
36         }
37         sqlSession.close();
38     }
39 
40     @Test
41     public void test03(){
42         SqlSession sqlSession = MybatisUtils.getSqlSession();
43         UserDao mapper = sqlSession.getMapper(UserDao.class);
44         List<User> users = mapper.getUsers();
45         for (User user:users){
46             System.out.println(user);
47         }
48         sqlSession.close();
49     }
50 
51     @Test
52     public void test04(){
53         SqlSession sqlSession = MybatisUtils.getSqlSession();
54         UserDao mapper = sqlSession.getMapper(UserDao.class);
55         int i = mapper.deleteUser(2);
56         System.out.println(i);
57         sqlSession.close();
58     }
59     @Test
60     public void test05(){
61         SqlSession sqlSession = MybatisUtils.getSqlSession();
62         UserDao mapper = sqlSession.getMapper(UserDao.class);
63         int i = mapper.insertUser(new User(3,"test"));
64         System.out.println(i);
65         sqlSession.close();
66     }
67 
68     @Test
69     public void test06(){
70         SqlSession sqlSession = MybatisUtils.getSqlSession();
71         UserDao mapper = sqlSession.getMapper(UserDao.class);
72         int i =  mapper.update(new User(3,"test02"));
73         System.out.println(i);
74         sqlSession.close();
75     }
76 }
View Code

測試

本質:反射機制實現

底層:動態代理


MyBatis詳細執行流程


8.3 注解CURD
//方法存在多個參數,所有的參數前面必須加上@Param("id")注解
@Delete("delete from user where id = ${uid}")
int deleteUser(@Param("uid") int id);
關於@Param( )注解

基本類型的參數或者String類型,需要加上
引用類型不需要加
如果只有一個基本類型的話,可以忽略,但是建議大家都加上
我們在SQL中引用的就是我們這里的@Param()中設定的屬性名
#{} 和 ${}

9、Lombok
Lombok項目是一個Java庫,它會自動插入編輯器和構建工具中,Lombok提供了一組有用的注釋,用來消除Java類中的大量樣板代碼。僅五個字符(@Data)就可以替換數百行代碼從而產生干凈,簡潔且易於維護的Java類。

使用步驟:

在IDEA中安裝Lombok插件

在項目中導入lombok的jar包

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>

 


在程序上加注解

 1 @Getter and @Setter
 2 @FieldNameConstants
 3 @ToString
 4 @EqualsAndHashCode
 5 @AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
 6 @Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
 7 @Data
 8 @Builder
 9 @SuperBuilder
10 @Singular
11 @Delegate
12 @Value
13 @Accessors
14 @Wither
15 @With
16 @SneakyThrows
17 @val

說明:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String password;
}

 對於mybatis來說復雜的sql語句還是用配置文件來做,下面兩個點是多對一一對多的介紹。推薦使用聯合嵌套查詢

 

10、多對一處理

多個學生一個老師;

數據庫表

 1 CREATE TABLE `teacher` (
 2   `id` INT(10) NOT NULL,
 3   `name` VARCHAR(30) DEFAULT NULL,
 4   PRIMARY KEY (`id`)
 5 ) ENGINE=INNODB DEFAULT CHARSET=utf8
 6 
 7 INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老師'); 
 8 
 9 CREATE TABLE `student` (
10   `id` INT(10) NOT NULL,
11   `name` VARCHAR(30) DEFAULT NULL,
12   `tid` INT(10) DEFAULT NULL,
13   PRIMARY KEY (`id`),
14   KEY `fktid` (`tid`),
15   CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
16 ) ENGINE=INNODB DEFAULT CHARSET=utf8INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1'); 
17 INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小紅', '1'); 
18 INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小張', '1'); 
19 INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1'); 
20 INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');
View Code

1. 測試環境搭建

  1. 導入lombok
  2. 新建實體類Teacher,Student
  3. 建立Mapper接口
  4. 建立Mapper.xml文件
  5. 在核心配置文件中綁定注冊我們的Mapper接口或者文件 【方式很多,隨心選】
  6. 測試查詢是否能夠成功

具體過程為

先在maven里面添加依賴

 1     <dependencies>
 2         <dependency>
 3             <groupId>org.projectlombok</groupId>
 4             <artifactId>lombok</artifactId>
 5             <version>1.18.16</version>
 6         </dependency>
 7         <dependency>
 8             <groupId>junit</groupId>
 9             <artifactId>junit</artifactId>
10             <version>4.13</version>
11             <scope>test</scope>
12         </dependency>
13         <dependency>
14             <groupId>mysql</groupId>
15             <artifactId>mysql-connector-java</artifactId>
16             <version>8.0.15</version>
17         </dependency>
18         <dependency>
19             <groupId>org.mybatis</groupId>
20             <artifactId>mybatis</artifactId>
21             <version>3.5.4</version>
22         </dependency>
23         <dependency>
24             <groupId>log4j</groupId>
25             <artifactId>log4j</artifactId>
26             <version>1.2.12</version>
27         </dependency>
28 
29     </dependencies>
View Code

配置文件

db.properties

1 driver=com.mysql.cj.jdbc.Driver
2 url=jdbc:mysql://localhost:3306/student?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
3 username=root
4 password=root
View Code

log4j.properties

 1 #將等級為DEBUG的日志信息輸出到console和file這兩個目的地,console和file的定義在下面的代碼
 2 log4j.rootLogger=DEBUG,console,file
 3 #控制台輸出的相關設置
 4 log4j.appender.console = org.apache.log4j.ConsoleAppender
 5 log4j.appender.console.Target = System.out
 6 log4j.appender.console.Threshold=DEBUG
 7 log4j.appender.console.layout = org.apache.log4j.PatternLayout
 8 log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
 9 #文件輸出的相關設置
10 log4j.appender.file = org.apache.log4j.RollingFileAppender
11 log4j.appender.file.File=./log/rzp.log
12 log4j.appender.file.MaxFileSize=10mb
13 log4j.appender.file.Threshold=DEBUG
14 log4j.appender.file.layout=org.apache.log4j.PatternLayout
15 log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
16 #日志輸出級別
17 log4j.logger.org.mybatis=DEBUG
18 log4j.logger.java.sql=DEBUG
19 log4j.logger.java.sql.Statement=DEBUG
20 log4j.logger.java.sql.ResultSet=DEBUG
21 log4j.logger.java.sq1.PreparedStatement=DEBUG
View Code

mybatis-config.xml

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE configuration
 3         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4         "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5 <!--configuration核心配置文件-->
 6 <configuration>
 7     <properties resource="db.properties"/>
 8 <!--    <settings>-->
 9 <!--&lt;!&ndash;        <setting name="logImpl" value="log4j"/>&ndash;&gt;-->
10 <!--    </settings>-->
11     <typeAliases>
12         <typeAlias type="com.bupt.pojo.Teacher" alias="Teacher"/>
13         <typeAlias type="com.bupt.pojo.Student" alias="Student"/>
14         <typeAlias type="com.bupt.pojo.Student2" alias="Student2"/>
15         <typeAlias type="com.bupt.pojo.Teacher2" alias="Teacher2"/>
16     </typeAliases>
17     <environments default="development">
18         <environment id="development">
19             <transactionManager type="JDBC"></transactionManager>
20             <dataSource type="POOLED">
21                 <property name="driver" value="${driver}"/>
22                 <property name="url" value="${url}"/>
23                 <property name="username" value="${username}"/>
24                 <property name="password" value="${password}"/>
25             </dataSource>
26         </environment>
27     </environments>
28 
29 <!--  無論使用包掃描(package)還是使用class方法要注意一下
30   (1)接口和他的Mapper配置文件必須同名
31   (2)接口和他的Mapper配置文件必須在同一個包里面
32   -->
33 <!--    <mappers>-->
34 <!--        <mapper  resource="com/bupt/dao/StudentMapper.xml"/>-->
35 <!--        <mapper  class="com.bupt.dao.TeacherMapper"/>-->
36 <!--    </mappers>-->
37 
38     <mappers>
39         <package name="com.bupt.dao"/>
40     </mappers>
41 </configuration>
View Code

utils包下的MybatisUtils文件

 1 package com.bupt.utils;
 2 
 3 import org.apache.ibatis.io.Resources;
 4 import org.apache.ibatis.session.SqlSession;
 5 import org.apache.ibatis.session.SqlSessionFactory;
 6 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 7 
 8 import java.io.IOException;
 9 import java.io.InputStream;
10 
11 public class MybatisUtils {
12     static InputStream resourceAsStream = null;
13     static SqlSessionFactory build = null;
14     static {
15 
16         try {
17             String resource = "mybatis-config.xml";
18             resourceAsStream = Resources.getResourceAsStream(resource);
19             build = new SqlSessionFactoryBuilder().build(resourceAsStream);
20         } catch (IOException e) {
21             e.printStackTrace();
22         }
23     }
24 
25     public static SqlSession getSqlSession(){
26         SqlSession sqlSession = build.openSession();
27         return sqlSession;
28     }
29 }
View Code

實體類Student和Teacher

package com.bupt.pojo;

import lombok.Data;

@Data
public class Student {
    private int id;
    private String name;
    private Teacher teacher;
}
Student
1 package com.bupt.pojo;
2 
3 import lombok.Data;
4 
5 @Data
6 public class Teacher {
7     private int id;
8     private String name;
9 }
Teacher

Mapper接口和對應的配置文件

StudentMapper

 1 package com.bupt.dao;
 2 
 3 import com.bupt.pojo.Student;
 4 
 5 import java.util.List;
 6 
 7 public interface StudentMapper {
 8     //查詢所有學生的信息,及其對應的老師的信息
 9     public List<Student> getStudent();
10     public List<Student> getStudent2();
11 }
View Code

StudentMapper.xm;

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE mapper
 3         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 5 <mapper namespace="com.bupt.dao.StudentMapper">
 6     
 7     <select id="getStudent2"  resultMap="StudentTeacher2">
 8         select s.id, s.name, t.name  tname
 9         from student s,teacher t
10         where s.tid = t.id
11     </select>
12     <resultMap id="StudentTeacher2" type="Student">
13         <result property="id" column="id"/>
14         <result property="name" column="name"/>
15         <association property="teacher" javaType="Teacher" >
16             <result property="name" column="tname"/>
17         </association>
18     </resultMap>
19     
20     
21 <!--    方式一   按照子查詢的方式    -->
22     <select id="getStudent" resultMap="StudentTeacher">
23         select * from student;
24     </select>
25 
26     <resultMap id="StudentTeacher" type="Student">
27         <result property="id" column="id"/>
28         <result property="name" column="name"/>
29         <association property="teacher" column="tid" javaType="Teacher"  select="getTeacher"/>
30     </resultMap>
31 
32     <select id="getTeacher" resultType="Teacher">
33         select * from teacher where id=#{tid}
34     </select>
35 </mapper>
View Code

TeacherMapper

 1 package com.bupt.dao;
 2 
 3 import com.bupt.pojo.Teacher;
 4 import org.apache.ibatis.annotations.Param;
 5 import org.apache.ibatis.annotations.Select;
 6 
 7 public interface TeacherMapper {
 8 
 9     @Select("select * from teacher where id=#{id}")
10     Teacher getTeacher(@Param("id") int id);
11 }
View Code

TeacherMapper.xml

1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE mapper
3         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
4         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5 <mapper namespace="com.bupt.dao.TeacherMapper">
6 
7 </mapper>
View Code

測試

 1     @Test
 2     public void test01(){
 3         SqlSession sqlSession = MybatisUtils.getSqlSession();
 4         TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
 5         Teacher teacher = mapper.getTeacher(1);
 6         System.out.println(teacher);
 7         sqlSession.close();
 8     }
 9 
10     @Test
11     public void test02(){
12         SqlSession sqlSession = MybatisUtils.getSqlSession();
13         StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
14         for (Student student : mapper.getStudent()) {
15             System.out.println(student);
16         }
17         sqlSession.close();
18     }
19 
20     @Test
21     public void test03(){
22         SqlSession sqlSession = MybatisUtils.getSqlSession();
23         StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
24         for (Student student : mapper.getStudent2()) {
25             System.out.println(student);
26         }
27         sqlSession.close();
28     }
View Code

其中最重要的就是兩種處理方式

方式一:按照查詢嵌套處理

<!--
     思路:
        1. 查詢所有的學生信息
        2. 根據查詢出來的學生的tid尋找特定的老師 (子查詢)
    -->
<select id="getStudent" resultMap="StudentTeacher">
    select * from student
</select>
<resultMap id="StudentTeacher" type="student">
    <result property="id" column="id"/>
    <result property="name" column="name"/>
    <!--復雜的屬性,我們需要單獨出來 對象:association 集合:collection-->
    <collection property="teacher" column="tid" javaType="teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="teacher">
    select * from teacher where id = #{id}
</select>

方式二:按照結果嵌套處理

 1     <!--按照結果進行查詢-->
 2     <select id="getStudent2" resultMap="StudentTeacher2">
 3         select s.id sid , s.name sname, t.name tname
 4         from student s,teacher t
 5         where s.tid=t.id
 6     </select>
 7     <!--結果封裝,將查詢出來的列封裝到對象屬性中-->
 8     <resultMap id="StudentTeacher2" type="student">
 9         <result property="id" column="sid"/>
10         <result property="name" column="sname"/>
11         <association property="teacher" javaType="teacher">
12             <result property="name" column="tname"></result>
13         </association>
14     </resultMap>

回顧Mysql多對一查詢方式:

  • 子查詢 (按照查詢嵌套)
  • 聯表查詢 (按照結果嵌套)

11、一對多處理

一個老師多個學生;

對於老師而言,就是一對多的關系;

1. 環境搭建

實體類

1 @Data
2 public class Student {
3     private int id;
4     private String name;
5     private int tid;
6 }
1 @Data
2 public class Teacher {
3     private int id;
4     private String name;
5 
6     //一個老師擁有多個學生
7     private List<Student> students;
8 }

2. 按照結果嵌套嵌套處理(推薦使用的查詢方式)

 1 <!--按結果嵌套查詢-->
 2 <select id="getTeacher" resultMap="StudentTeacher">
 3     SELECT s.id sid, s.name sname,t.name tname,t.id tid FROM student s, teacher t
 4     WHERE s.tid = t.id AND tid = #{tid}
 5 </select>
 6 <resultMap id="StudentTeacher" type="Teacher">
 7     <result property="id" column="tid"/>
 8     <result property="name" column="tname"/>
 9     <!--復雜的屬性,我們需要單獨處理 對象:association 集合:collection
10     javaType=""指定屬性的類型!
11     集合中的泛型信息,我們使用ofType獲取
12     -->
13     <collection property="students" ofType="Student">
14         <result property="id" column="sid"/>
15         <result property="name" column="sname"/>
16         <result property="tid" column="tid"/>
17     </collection>
18 </resultMap>

子查詢方式實現一對多

 1     <select id="getTeacher2" resultMap="TeacherStudent2">
 2             select * from teacher where id=#{tid}
 3     </select>
 4     <resultMap id="TeacherStudent2" type="Teacher2">
 5         <collection property="student" javaType="ArrayList" ofType="Student2" select="getTeacherStudent2" column="id"/>
 6     </resultMap>
 7     <select id="getTeacherStudent2" resultType="Student2">
 8         select *
 9         from student where tid = #{tid};
10     </select>

小結
關聯 - association 【多對一】
集合 - collection 【一對多】
javaType & ofType
JavaType用來指定實體類中的類型
ofType用來指定映射到List或者集合中的pojo類型,泛型中的約束類型
​ 注意點:

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

面試高頻

  • Mysql引擎
  • InnoDB底層原理
  • 索引
  • 索引優化

12、動態SQL
什么是動態SQL:動態SQL就是根據不同的條件生成不同的SQL語句

所謂的動態SQL,本質上還是SQL語句,只是我們可以在SQL層面,去執行一個邏輯代碼

動態 SQL 是 MyBatis 的強大特性之一。如果你使用過 JDBC 或其它類似的框架,你應該能理解根據不同條件拼接 SQL 語句有多痛苦,例如拼接時要確保不能忘記添加必要的空格,還要注意去掉列表最后一個列名的逗號。利用動態 SQL,可以徹底擺脫這種痛苦。

搭建環境

CREATE TABLE `mybatis`.`blog`  (
  `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '博客id',
  `title` varchar(30) NOT NULL COMMENT '博客標題',
  `author` varchar(30) NOT NULL COMMENT '博客作者',
  `create_time` datetime(0) NOT NULL COMMENT '創建時間',
  `views` int(30) NOT NULL COMMENT '瀏覽量',
  PRIMARY KEY (`id`)
)

創建一個基礎工程

導包

編寫配置文件

編寫實體類

1 @Data
2 public class Blog {
3 private int id;
4 private String title;
5 private String author;
6 
7 private Date createTime;// 屬性名和字段名不一致
8 private int views;
9 }

BlogMapper

 1 package com.bupt.dao;
 2 
 3 import com.bupt.pojo.Blog;
 4 
 5 import java.util.List;
 6 import java.util.Map;
 7 
 8 public interface BlogMapper {
 9 
10     int addBook(Blog blog);
11 
12     List<Blog> queryBlogIf(Map map);
13 
14     List<Blog> queryChoose(Map map);
15 
16     //更新博客
17     int updateBlog(Map map);
18 }
View Code

BlogMapper.xml

通過使用動態sql可以動態的編寫sql語句,並且動態sql可以自動去除多余的and和where和,等多余的內容。

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE mapper 
 3         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 5 <mapper namespace="com.bupt.dao.BlogMapper">
 6 
 7     <insert id="addBook" parameterType="blog">
 8         insert into blog(id,title,author,create_time,views) values (#{id},#{title},#{author},#{createTime},#{views});
 9     </insert>
10 
11     <select id="queryBlogIf" parameterType="map" resultType="blog">
12         select * from blog
13        <where>
14            <if test="title != null">
15                title = #{title}
16            </if>
17            <if test="author != null">
18                and author = #{author}
19            </if>
20        </where>
21     </select>
22 
23     <select id="queryChoose" parameterType="map" resultType="blog">
24         select * from blog
25         <where>
26             <choose>
27                 <when test="title != null">
28                     title = #{title}
29                 </when>
30                 <when test="author !=null">
31                     and author = #{author}
32                 </when>
33                 <otherwise>
34                     and view = #{views}
35                 </otherwise>
36             </choose>
37         </where>
38     </select>
39 
40     <update id="updateBlog" parameterType="map">
41         update blog
42         <set>
43             <if test="title != null">
44                 title = #{title},
45             </if>
46             <if test="author != null">
47                 author = #{author}
48             </if>
49         </set>
50         where id = #{id}
51     </update>
52 
53 
54 </mapper>

SQL片段
有的時候,我們可能會將一些功能的部分抽取出來,方便服用!

使用SQL標簽抽取公共部分可

<sql id="if-title-author">
<if test="title!=null">
title = #{title}
</if>
<if test="author!=null">
and author = #{author}
</if>
</sql>


在需要使用的地方使用Include標簽引用即可

<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from blog
<where>
<include refid="if-title-author"></include>
</where>
</select>

13、緩存
13.1 簡介


查詢 : 連接數據庫,耗資源

​ 一次查詢的結果,給他暫存一個可以直接取到的地方 --> 內存:緩存

我們再次查詢的相同數據的時候,直接走緩存,不走數據庫了

什么是緩存[Cache]?

  • 存在內存中的臨時數據。
  • 將用戶經常查詢的數據放在緩存(內存)中,用戶去查詢數據就不用從磁盤上(關系型數據庫文件)查詢,從緩存中查詢,從而提高查詢效率,解決了高並發系統的性能問題

為什么使用緩存?

  • 減少和數據庫的交互次數,減少系統開銷,提高系統效率

什么樣的數據可以使用緩存?

  • 經常查詢並且不經常改變的數據 【可以使用緩存】

13.2 MyBatis緩存

  • MyBatis包含一個非常強大的查詢緩存特性,它可以非常方便的定制和配置緩存,緩存可以極大的提高查詢效率。
  • MyBatis系統中默認定義了兩級緩存:一級緩存和二級緩存
    •   默認情況下,只有一級緩存開啟(SqlSession級別的緩存,也稱為本地緩存)
    •   二級緩存需要手動開啟和配置,他是基於namespace級別的緩存。
    •   為了提高可擴展性,MyBatis定義了緩存接口Cache。我們可以通過實現Cache接口來定義二級緩存。

13.3 一級緩存
一級緩存也叫本地緩存:SqlSession
與數據庫同一次會話期間查詢到的數據會放在本地緩存中
以后如果需要獲取相同的數據,直接從緩存中拿,沒必要再去查詢數據庫
測試步驟:

開啟日志

測試在一個Session中查詢兩次記錄

    @Test
    public void test1() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.getUserById(1);
        System.out.println(user);

        System.out.println("=====================================");

        User user2 =  mapper.getUserById(1);
        System.out.println(user2 == user);
    }

發現只進行了一次數據庫連接

 

 

緩存失效的情況:

  1. 查詢不同的東西

  2. 增刪改操作,可能會改變原來的數據,所以必定會刷新緩存

  3. 查詢不同的Mapper.xml

  4. 手動清理緩存

    sqlSession.clearCache();

 

13.4 二級緩存

  • 二級緩存也叫全局緩存,一級緩存作用域太低了,所以誕生了二級緩存
  • 基於namespace級別的緩存,一個名稱空間,對應一個二級緩存
  • 工作機制
    •   一個會話查詢一條數據,這個數據就會被放在當前會話的一級緩存中
    •   如果會話關閉了,這個會員對應的一級緩存就沒了;但是我們想要的是,會話關閉了,一級緩存中的數據被保存到二級緩存中
    •   新的會話查詢信息,就可以從二級緩存中獲取內容
    •   不同的mapper查詢出的數據會放在自己對應的緩存(map)中
    • 一級緩存開啟(SqlSession級別的緩存,也稱為本地緩存)

 

二級緩存需要手動開啟和配置,他是基於namespace級別的緩存。
為了提高可擴展性,MyBatis定義了緩存接口Cache。我們可以通過實現Cache接口來定義二級緩存。
步驟:

 

開啟全局緩存

 

<!--顯示的開啟全局緩存,默認也是開啟的,所以可以不寫,但是寫上其實是起到提醒的作用-->
<setting name="cacheEnabled" value="true"/>
在Mapper.xml中使用緩存

 

<!--在當前Mapper.xml中使用二級緩存-->
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>

 

  1. 測試

    1. 問題:我們需要將實體類序列化,否則就會報錯

 

小結:

 

  • 只要開啟了二級緩存,在同一個Mapper下就有效
  • 所有的數據都會放在一級緩存中
  • 只有當前會話提交,或者關閉的時候,才會提交到二級緩存中

 

13.5 緩存原理

 

 

 


注意:

 

只有查詢才有緩存,根據數據是否需要緩存(修改是否頻繁選擇是否開啟)useCache=“true”

 

<select id="getUserById" resultType="user" useCache="true"> select * from user where id = #{id} </select>

 

13.6 自定義緩存-ehcache
Ehcache是一種廣泛使用的開源Java分布式緩存。主要面向通用緩存

 

導包

 

<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.2.1</version>
</dependency>

在mapper中指定使用我們的ehcache緩存實現

 

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM