MyBatis

124 阅读16分钟

1. 简介

1.1maven仓库:

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.9</version>
</dependency>    

1.2持久化

数据持久化:

1.持久化就是将程序的数据持久状态和瞬间状态转化的过程
2.内存:断电即失
3.数据库(jdbc),io文件持久化

为什么需要持久化:

有一些对象需要保存,不能因为内存的断电即失而丢掉

1.3持久层

dao层,service层,controller层:

1.完成持久化工作的代码块
2.界限十分明显

2.第一个mybatis程序

2.1环境搭建

2.1.1搭建数据库

图片.png

2.1.2新建项目

一.新建maven项目
二.删除src

2.2导入maven依赖

mysql驱动

<dependency>
    <!--mysql驱动-->
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>

mybatis依赖

图片.png

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.9</version>
</dependency>

junit

<!--junit-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

2.3编写代码

编写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>
     <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/mybatis?useSSL=false&amp;characterEncoding=UTF-8"/>  //需要连接的数据库的表
                 <property name="username" value="root"/> //自己数据库的名称
                 <property name="password" value="root"/>  //自己数据库的密码
             </dataSource>
         </environment>
     </environments>
     <mappers>
 <!--每一个mapper.xml都需要在mybatis核心配置文件中注册!-->
         <mapper resource="com/dao/UserMapper.xml"/>
     </mappers>
 </configuration>     

2.4绑定每一个mapper.xml

<mappers>
<!--每一个mapper.xml都需要在mybatis核心配置文件中注册!-->
     <mapper resource="com/dao/UserMapper.xml"/>
</mappers>    

2.5测试

2.5.1实体类

package com.ran.pojo;

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

    public User() {
    }    

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

    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 getPwd() {
        return pwd;
    }

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

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

2.5.2接口

public interface UserMapper {
    public User select(int uid);
    public void save(User user);
    public int update(User user);
    public void delete(int uid);
}

2.5.3接口实现类

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper  namespace="com.example.demo_mybatis.UserMapper">

    <!--查询操作-->
    <select id="select" resultType="com.example.demo_mybatis.User">
        select * from user where uid = #{id}
    </select>

    <!--插入操作-->
    <insert id="save" parameterType="com.example.demo_mybatis.User">
        insert into user(username,password,email) values(#{username},#{password},#{email});
    </insert>

    <!--修改操作-->
    <update id="update" parameterType="com.example.demo_mybatis.User">
        update user set username = #{username},password = #{password} where uid = #{uid}
    </update>

    <!--删除操作-->
    <delete id="delete" parameterType="java.lang.Integer">
        delete from user where uid = #{uid}
    </delete>

</mapper>

2.5.4测试类

public class TestDome {

    //查询操作
    @Test
    public void testUser1() throws IOException {

        String resource = "mybatis.config.xml";
        //加载mybatis的主配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 创建一个mybatis的工厂类
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过工厂获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取UserMapper的动态代理
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //查询select的查询
        User user = mapper.select(4);
        System.out.println(user);
        //关闭sqlSession
        sqlSession.close();
    }

    //插入操作
    @Test
    public void testUser2() throws IOException {

        //模拟user对象
        User user=new User();
        user.setUsername("ck");
        user.setPassword("123");
        user.setEmail("145@qq.com");
        //加载mybatis的主配置文件
        String resource = "mybatis.config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 创建一个mybatis的工厂类
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过工厂获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取UserMapper的动态代理
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
       mapper.save(user);
       sqlSession.commit();
       sqlSession.close();
    }

    //修改操作
    @Test
    public void testUser3() throws IOException {
        //加载mybatis的主配置文件
        String resource = "mybatis.config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 创建一个mybatis的工厂类
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过工厂获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //执行操作
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //模拟user对象
        User user=new User();
        user.setUid(12);
        user.setUsername("kun");
        user.setPassword("111");
        mapper.update(user);
        //mybatis更新操作,提交事务
        sqlSession.commit();
        //关闭sqlSession
        sqlSession.close();
    }

    //删除操作
    @Test
    public void testUser4() throws IOException {

        //加载mybatis的主配置文件
        String resource = "mybatis.config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 创建一个mybatis的工厂类
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过工厂获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //执行操作
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.delete(12);

        //mybatis更新操作,提交事务
        sqlSession.commit();
        //关闭sqlSession
        sqlSession.close();
    }
}

2.5.5资源导出问题: 在build中配置resoure,来防止我们资源导出问题

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

3.编写mybatis工具类

package com.utils;

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;

//SqlSessionFactory -->SqlSession
public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            String resource ="mybatis-config.xml";
            //使用mybatis第一步:获取SqlSessionFactory对象
            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(//ture);//值设置为ture可以自动提交事务
    }
}

4.CRUD

1.namespace

namespace中的包名要和Dao/mapper接口的包名一致!

mybatis获取参数值的两种方式:${}和#{}

${}本质字符串拼接(注意单引号问题)
#{}本质占位符赋值

2.select

选择,查询语句:

1.id:就是对应的namespace中的方法名
2.resultType:sql语句执行的返回值!
3.parameType:参数类型

1.1编写接口

//查询所以用户
    List<User> getUserList();
    //根据id查询用户
    User getUserById(int id);
    //增加一个用户

1.2编写对应的mapper中的sql语句

 <!--查询语句-->
    <select id="getUserList" resultType="com.pojo.User">
        select * from users
    </select>
    <select id="getUserById" resultType="com.pojo.User" parameterType="int">
        select * from users where id=#{id}
    </select>

1.3测试

   @Test
    public void Test(){
        //第一步获得sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //方式一:getMapper  第二部执行sql
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        List<User> userList = mapper.getUserList();
        for (User u:userList
             ) {
            System.out.println(u);
        }
        //关闭sqlSession
        sqlSession.close();
    }
    @Test
    public void getUserById(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        User user = mapper.getUserById(2);
        System.out.println(user);
        //关闭sqlSession
        sqlSession.close();
    }

3.insert

<!--对象中的属性,可以直接取出来-->
<insert id="addUser" parameterType="com.pojo.User">
    insert into users (id,name,pwd) value (#{id},#{name},#{pwd})
</insert>

4.update

<!--    修改用户-->
    <update id="updateUser" parameterType="com.pojo.User">
        update users set name=#{name},pwd=#{pwd} where id=#{id}
    </update>

5.delete

<!--    删除用户-->
<delete id="deleteUser" parameterType="int" >
    delete from users where id=#{id}
</delete>

6:重点:增删改需要提交事物

// 提交事务
   sqlSession.commit();

7:map:

map传递参数,直接在sql中取出key

假如,我们的实体类,或者数据库的表,字段或者参数过多,我们应当考虑适应map!

接口:

//map
int addUser2(Map<String,Object> map);

接口实现类:

<!--    map-->
    <insert id="addUser2" parameterType="map">
        insert into users (id,name,pwd) value (#{userid},#{username},#{userpassword})
    </insert>

测试类:

@Test
    public void addUser2(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        HashMap<String, Object> map = new HashMap<>();
        map.put("userid",5);
        map.put("username","rj");
        map.put("userpassword","123435425");
        int i = mapper.addUser2(map);if(i>0){
            System.out.println("添加成功");
        }else {
            System.out.println("添加失败");
        }
        //提交事务
        sqlSession.commit();
        //关闭sqlSession
        sqlSession.close();
    }

模糊查询:使用通配符 %

 <select id="getUserLike" resultType="com.pojo.User">
        select * from users where name like #{value}
    </select>
<select id="getUserLike" resultType="com.pojo.User">    
    select * from users where name like "%" #{value} "%"
</select>
 @Test
    public void getUserLike(){
        //        第一步获得sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
//        方式一:getMapper  第二部执行sql
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        List<User> userList = mapper.getUserLike("%李%");
        for (User u:userList
        ) {
            System.out.println(u);
        }
        //关闭sqlSession
        sqlSession.close();
    }

5.配置解析

1.核心配置文件

configuration(配置)
properties(属性 ,如数据库的配置jdbc.properties, 系统参数配置 system.properties)
settings(设置)
typeAliases(设置某个类型的别名 属性:type:设置需要设置别名的类型  alias:别名,若不设置属性,那么该类型拥有默认的别名,即类名且不区分大小写)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器,引入映射文件)

2.环境配置(environments)

MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中
<environments default="development"></environments>

3 .事务管理器(transactionManager)

在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):

  • JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
  • MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为

4.数据源(dataSource)

dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。

  • 大多数 MyBatis 应用程序会按示例中的例子来配置数据源。虽然数据源配置是可选的,但如果要启用延迟加载特性,就必须配置数据源。

有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]"):

UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择。 性能表现则依赖于使用的数据库,对某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。UNPOOLED 类型的数据源仅仅需要配置以下 5 种属性:

  • driver – 这是 JDBC 驱动的 Java 类全限定名(并不是 JDBC 驱动中可能包含的数据源类)。
  • url – 这是数据库的 JDBC URL 地址。
  • username – 登录数据库的用户名。
  • password – 登录数据库的密码。
  • defaultTransactionIsolationLevel – 默认的连接事务隔离级别。
  • defaultNetworkTimeout – 等待数据库操作完成的默认网络超时时间(单位:毫秒)。查看 java.sql.Connection#setNetworkTimeout() 的 API 文档以获取更多信息。

作为可选项,你也可以传递属性给数据库驱动。只需在属性名加上“driver.”前缀即可,例如:

  • driver.encoding=UTF8

这将通过 DriverManager.getConnection(url, driverProperties) 方法传递值为 UTF8encoding 属性给数据库驱动。

POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。

除了上述提到 UNPOOLED 下的属性外,还有更多属性用来配置 POOLED 的数据源:

  • poolMaximumActiveConnections – 在任意时间可存在的活动(正在使用)连接数量,默认值:10
  • poolMaximumIdleConnections – 任意时间可能存在的空闲连接数。
  • poolMaximumCheckoutTime – 在被强制返回之前,池中连接被检出(checked out)时间,默认值:20000 毫秒(即 20 秒)
  • poolTimeToWait – 这是一个底层设置,如果获取连接花费了相当长的时间,连接池会打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直失败且不打印日志),默认值:20000 毫秒(即 20 秒)。
  • poolMaximumLocalBadConnectionTolerance – 这是一个关于坏连接容忍度的底层设置, 作用于每一个尝试从缓存池获取连接的线程。 如果这个线程获取到的是一个坏的连接,那么这个数据源允许这个线程尝试重新获取一个新的连接,但是这个重新尝试的次数不应该超过 poolMaximumIdleConnectionspoolMaximumLocalBadConnectionTolerance 之和。 默认值:3(新增于 3.4.5)
  • poolPingQuery – 发送到数据库的侦测查询,用来检验连接是否正常工作并准备接受请求。默认是“NO PING QUERY SET”,这会导致多数数据库驱动出错时返回恰当的错误消息。
  • poolPingEnabled – 是否启用侦测查询。若开启,需要设置 poolPingQuery 属性为一个可执行的 SQL 语句(最好是一个速度非常快的 SQL 语句),默认值:false。
  • poolPingConnectionsNotUsedFor – 配置 poolPingQuery 的频率。可以被设置为和数据库连接超时时间一样,来避免不必要的侦测,默认值:0(即所有连接每一时刻都被侦测 — 当然仅当 poolPingEnabled 为 true 时适用)。

JNDI – 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。这种数据源配置只需要两个属性:

  • initial_context – 这个属性用来在 InitialContext 中寻找上下文(即,initialContext.lookup(initial_context))。这是个可选属性,如果忽略,那么将会直接从 InitialContext 中寻找 data_source 属性。
  • data_source – 这是引用数据源实例位置的上下文路径。提供了 initial_context 配置时会在其返回的上下文中进行查找,没有提供时则直接在 InitialContext 中查找。

和其他数据源配置类似,可以通过添加前缀“env.”直接把属性传递给 InitialContext。比如:

  • env.encoding=UTF8

这就会在 InitialContext 实例化时往它的构造方法传递值为 UTF8encoding 属性。

5.属性(properties)

使用properties属性来实现引用配置文件

编写一个配置文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;characterEncoding=UTF-8
username=root
password=root

6.类型别名(typeAliases)

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写

<!--    可以给实体类取别名-->
    <typeAliases>
        <typeAlias type="com.pojo.User" alias="User"/>
    </typeAliases>

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean

扫描实体类的包,他的默认别名就是这个类的类名,首字母小写

   <typeAliases>
        <package name="com.pojo"/> <!-- user-->
    </typeAliases>

使用注解@Alias("xxx")不默认小写

@Alias("xxx")
public class User {

}

7.设置(settings)

1647340878920.png

1647340897573.png

8.映射器(mappers)

注册绑定我们的Mapper文件

第一种方式:

<mappers>
<!--每一个mapper.xml都需要在mybatis核心配置文件中注册!-->
        <mapper resource="com/dao/UserMapper.xml"/>
    </mappers>

第二种方式:使用class文件绑定注册

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

注意点:

接口和mapper配置文件必须同名!

接口和mapper配置文件必须在同一个包下!

第三种方式:package:使用扫描包进行注入绑定

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

注意点:

接口和mapper配置文件必须同名!

接口和mapper配置文件必须在同一个包下!

9.resultMap

1647345606622.png

1647345586785.png 结果集映射

sql:id name pwd

实体类:id name password

<!--    结果集映射-->
   <resultMap id="UserMap" type="User">
<!--column:数据库中的字段     property:实体类中的属性      -->
       <result column="id" property="id"/>
       <result column="name" property="name"/>
       <result column="pwd" property="password"/>
   </resultMap>
    <select id="getUserById" resultMap="UserMap">
        select * from users where id=#{id}
    </select>

6.日志

6.1日志工厂

如果数据库操作异常,我们需要排错,日志是最好的助手!

1647340897573.png

  • SLF4J

  • LOG4J(deprecated since 3.5.9)【掌握】

  • LOG4J2

  • JDK_LOGGING

  • COMMONS_LOGGING

  • STDOUT_LOGGING 【掌握】

  • NO_LOGGING

在mybatis中具体使用哪一个日志实现,在设置中设定!

STDOUT_LOGGING 标准日志输出

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

LOG4J(deprecated since 3.5.9)【掌握】

1.先导包

<dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.36</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.30</version>
        </dependency>

2:log4j. properties

#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
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=[%c]-%m%n

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/ran.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%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.PreparedStatement=DEBUG

3:配置log4j为日志的实现

<settings>
    <!--标准日志工厂实现-->
    <setting name="logImpl" value="LOG4J"/>    
</settings>
@Slf4j
public class MyTest01 { }

4:log4j的使用

1.在要使用时Log4j的类中,导入包import org.apache.log4j.Logger;

2.日志对象,参数为当前类的class

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

3.测试

@Test
    public void testLog4j(){
        logger.info("info进入testLog4j");
        logger.debug("debug进入testLog4j");
        logger.error("error进入testLog4j");
    }

7:分页

7.1使用limit分页

limit index, pagesize
index:当前页的起始索引
pagesize :每页显示的条数
pageNMum:当前页的页码
index=(pageNum-1 )*pagesize家

select * from users limit 0,2;

使用maybatis分页,核心sql

1接口

List<User> getByLimit(Map<String,Integer> map);

2mapper.xml

<!--    分页-->
    <select id="getByLimit" parameterType="map" resultMap="UserMap">
        select * from users limit #{startIndex},#{pageSize}
    </select>

3.测试

@Test
    public void getByLimit(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        HashMap<String, Integer> map = new HashMap<>();
        map.put("startIndex",0);
        map.put("pageSize",2);

        List<User> byLimit = mapper.getByLimit(map);
        for (User S: byLimit
             ) {
            System.out.println(S);
        }

        sqlSession.close();

    }

7.2 RowBounds分页 :不再使用sql实现

1,接口

//  分页2
    List<User> getByRowBounds() ;

2,mapper.xml

 <!--    分页2-->
    <select id="getByRowBounds" resultMap="UserMap">
        select * from users
    </select>

3.测试

 @Test
    public void getByRowBounds(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
//        通过RowBounds实现
        RowBounds bounds = new RowBounds(1,2);
//        通过java代码层面实现分页
        List<User> objects = sqlSession.selectList("com.dao.UserMapper.getByRowBounds",null,bounds);
        for (User u:objects
             ) {
            System.out.println(u);
        }
        sqlSession.close();
    }

8.使用注解开发

1.注解在接口上实现

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

2.需要在核心配置文件中绑定接口【重点】

<!--   绑定接口-->
    <mappers>
        <mapper class="com.dao.UserMapper"/>
       <!-- <mapper resource="com/dao/*Mapper.xml"/>  --> 通配注册该路径下所以的xml
    </mappers>

本质:反射机制实现

@Select("select * from users where id =#{id}")
    User getUserById(@Param("id") int id);//多个参数需要使用@Param("id"),来指定

3.关于@Param( )注解

  • 本类型的参数或者String类型,需要加上

  • 用类型不需要加

  • 如果基本类型的话,可以忽略,但是建议加上

  • 我们在sql中引用的就是我们这里的@Param(" ")中设定的值!

9.Lombok

使用步骤

1.在idea中安装Lombok插件!

2.在项目中导入Lombok的jar

 <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
      <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
          <version>1.18.22</version>
      </dependency>

3

Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows
@val
@var
experimental @var
@UtilityClass

10:多对一处理

多对一:关联
一对多:集合

10.1、按照查询嵌套处理

<!--
  思路:
  1.查询全部学生信息
  2.根据查询出来的学生tid,寻找到对应的老师 ,子查询
-->
 <select id="getStudent" resultMap="studentTeacher">
     select * from student
 </select>
<!--property:实体类中的属性  column:数据库中的字段-->
    <resultMap id="studentTeacher" type="Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
<!--复杂的属性,我们需要单独处理 对象:association  集合:collection-->
<!--property需要处理的多对一的属性,javaType属性的类型-->
        <association property="teacher" column="tid" javaType="Teacher" select="getTeachers"/>
    </resultMap>
    <select id="getTeachers" resultType="Teacher">
        select * from teacher where id =#{id}
    </select>

10.2、按照结果嵌套处理

<!--按照结果嵌套处理-->
    <select id="getStudent2" resultMap="studentTeacher2">
        SELECT  s.id as sid,s.name as sname,t.id as tid,t.name as tname from student as s,teacher as t;
    </select>
    <resultMap id="studentTeacher2" type="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <association property="teacher"  javaType="Teacher">
            <result property="name" column="tname"/>
            <result property="id" column="tid"/>
        </association>
    </resultMap>

10.3实体类

@Data
public class Student {
    private int id;
    private String name;
    //学生需要关联老师
    private Teacher teacher;
}
@Data
public class Teacher {
    private int id;
    private String name;
}

11一对多

11.1、实体类

@Data
public class Student {
    private int id;
    private String name;
    private int tid;
}

@Data
public class Teacher {
    private int id;
    private String name;
    //一个老师关联多个学生
    private List<Student> students
}

12.动态sql

if、

接口

 List<Person> getPerson(Map map);
<mapper namespace="com.dao.PersonMapper">
    <select id="getPerson" parameterType="map" resultType="Person">
        select * from person 
       <where>
         <if test="age != null ">
         age = #{age}
         </if>
         <if test="id != null">
            and id = #{id}
         </if>
      </where>    
    </select>
</mapper>

测试类

 @Test
    public void test02(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
        HashMap hashMap = new HashMap();
        hashMap.put("age",17);
        hashMap.put("id",1);
        List<Person> person = mapper.getPerson(hashMap);
        for (Person p:person
             ) {
            System.out.println(p);
        }
        sqlSession.close();
    }

choose、when、otherwise、

<select id="getPerson" parameterType="map" resultType="Person">
    select * from person 
    <where>
        <choose>
           <when test="age != null">
               age = #{age}
            </when>
            <when test="id != null">
            and id = #{id}
            </when>
            <otherwise>
            AND name = #{name}  <!--必须写入的值-->
           </otherwise>
        </choose>
    </where>

set、可以取消sql语句update中的逗号!

foreach:

mapper:

List<Person> getPersonId(Map map);

mapper.xml

<!--    select * from person where 1=1 and(id =1 or id=2 or id=3)-->
    <select id="getPersonId" resultType="person" parameterType="map">
        select * from person
<where>
    <foreach collection="ids" item="id" open="and (" separator="or" close=")">
        id =#{id}
    </foreach>
</where>
    </select>

测试类

    SqlSession sqlSession = MybatisUtils.getSqlSession();
        PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
        HashMap hashMap = new HashMap();
        ArrayList<Integer> ids = new ArrayList<>();
        ids.add(1);
        ids.add(2);
        hashMap.put("ids",ids);
        List<Person> personId = mapper.getPersonId(hashMap);
        for (Person p:personId
             ) {
            System.out.println(p);
        }
        sqlSession.close();
    }

13:缓存

一级缓存、在sqlsession的创建与关闭之间

二级缓存、

1647579217415.png

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

在当前mapper使用二级缓存

<cache/>

自定义缓存:ehcache

导入依赖

<!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
<dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-ehcache</artifactId>
    <version>1.2.1</version>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="true" monitoring="autodetect" dynamicConfig="true">
    <diskStore path="java.io.tmpdir" />
    <!--
     name:Cache的唯一标识
     maxElementsInMemory:内存中最大缓存对象数
     maxElementsOnDisk:磁盘中最大缓存对象数,若是0表示无穷大
     eternal:Element是否永久有效,一但设置了,timeout将不起作用
     overflowToDisk:配置此属性,当内存中Element数量达到maxElementsInMemory时,Ehcache将会Element写到磁盘中
     timeToIdleSeconds:设置Element在失效前的允许闲置时间。仅当element不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大
     timeToLiveSeconds:设置Element在失效前允许存活时间。最大时间介于创建时间
         和失效时间之间。仅当element不是永久有效时使用,默认是0.,也就是element存活时间无穷大
     diskPersistent:是否缓存虚拟机重启期数据
     diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒
     diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区
     memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)
     -->
    <defaultCache maxElementsInMemory="10000"
                  eternal="false"
                  timeToIdleSeconds="120"
                  timeToLiveSeconds="120"
                  overflowToDisk="true"
                  maxElementsOnDisk="10000000"
                  diskPersistent="false"
                  diskExpiryThreadIntervalSeconds="120"
                  memoryStoreEvictionPolicy="LRU" />
    <cache name="testCache" 
           eternal="false" 
           maxElementsInMemory="100"
           overflowToDisk="false" 
           diskPersistent="false" 
           timeToIdleSeconds="0"
           timeToLiveSeconds="300" 
           memoryStoreEvictionPolicy="LRU" />
</ehcache>

序列化:实现接口

implements Serializable

case when语法

1647677187111.png @MapKey

@MapKey("id")
    @ResultMap("BaseResultMap")
    @Select("select * from user where hotel_address = #{address};")
    Map<Long, User> getUserByAddress(@Param("address") String address);

14.通用mapper

14.1、简单查询

package Test01;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInterceptor;
import com.pojo.User;
import com.pojo.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.junit.Before;
import org.junit.Test;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.entity.Config;
import tk.mybatis.mapper.mapperhelper.MapperHelper;

import java.util.List;

@Slf4j
public class MyTest01 {
    private SqlSession session;
    @Before
    public void before(){

        PooledDataSource dataSource = new PooledDataSource();
        dataSource.setDriver("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;characterEncoding=UTF-8");
        dataSource.setUsername("root");
        dataSource.setPassword("root");

        TransactionFactory transactionFactory = new JdbcTransactionFactory();
        Environment environment = new Environment("development", transactionFactory, dataSource);
        Configuration configuration = new Configuration(environment);
        //配置mapper位置
        configuration.addMapper(UserMapper.class);
       //配置分页功能
        configuration.addInterceptor(new PageInterceptor());
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);

//从刚刚创建的 sqlSessionFactory 中获取 session
        session = sqlSessionFactory.openSession();
//创建一个MapperHelper
        MapperHelper mapperHelper = new MapperHelper();
//特殊配置
        Config config = new Config();
//主键自增回写方法,默认值MYSQL,详细说明请看文档
        config.setIDENTITY("MYSQL");
//支持getter和setter方法上的注解
        config.setEnableMethodAnnotation(true);
//设置 insert 和 update 中,是否判断字符串类型!=''
        config.setNotEmpty(true);
//校验Example中的类型和最终调用时Mapper的泛型是否一致
        config.setCheckExampleEntityClass(true);
//启用简单类型
        config.setUseSimpleType(true);
//枚举按简单类型处理
        config.setEnumAsSimpleType(true);
//自动处理关键字 - mysql
        config.setWrapKeyword("`{0}`");
//设置配置
        mapperHelper.setConfig(config);
//注册通用接口,和其他集成方式中的 mappers 参数作用相同
//4.0 之后的版本,如果类似 Mapper.class 这样的基础接口带有 @RegisterMapper 注解,就不必在这里注册
        mapperHelper.registerMapper(Mapper.class);
//配置 mapperHelper 后,执行下面的操作
        mapperHelper.processConfiguration(session.getConfiguration());

    }
    @Test
    public void test01(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User();
        user.setId(1);
        User user1 = mapper.selectOne(user);
        log.info(user1.toString());
    }
    @Test
    public void test00(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        PageHelper.startPage(1,2);//分页实现
        List<User> users = mapper.selectAll();
        for(User user:users){
           log.info(user.toString());
        }

    }
    @Test
    public void test02(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User();
        int i = mapper.selectCount(user);
        System.out.println(i);
    }
    @Test
    public void test03(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User();
   user.setId(1);
        User user1 = mapper.selectByPrimaryKey(user);
        log.info(user1.toString());
    }
    @Test
    public void test04(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User();
        user.setId(1);
        List<User> select = mapper.select(user);
//        SELECT id,`name`,pwd,udate,email FROM users
        log.info(select.toString());
    }

}

<!--分页插件-->
     <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.3.0</version>
        </dependency>

14.2、复杂条件查询

   @Test
    public void test03(){
        SqlSession sqlSession = MyUtils.getSqlSession();
//   SELECT * from users WHERE (id = 2 OR pwd = "adf") and (name LIKE "李%")
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
         criteria.andEqualTo("id", 2);
         criteria.orEqualTo("pwd", "adf");

        Example.Criteria criteria1 = example.createCriteria();

        criteria1.andLike("name", "李%");
        example.or(criteria1);
        List<User> select = mapper.selectByExample(example);
        for (User u:select
             ) {
            log.info(u.toString());
        }
    }

14.3、方法介绍

Select
方法:List select(T record);
说明:根据实体中的属性值进行查询,查询条件使用等号

方法:T selectByPrimaryKey(Object key);
说明:根据主键字段进行查询,方法参数必须包含完整的主键属性,查询条件使用等号

方法:List selectAll();
说明:查询全部结果,select(null)方法能达到同样的效果

方法:T selectOne(T record);
说明:根据实体中的属性进行查询,只能有一个返回值,有多个结果是抛出异常,查询条件使用等号

方法:int selectCount(T record);
说明:根据实体中的属性查询总数,查询条件使用等号

Insert
方法:int insert(T record);
说明:保存一个实体,null的属性也会保存,不会使用数据库默认值

方法:int insertSelective(T record);
说明:保存一个实体,null的属性不会保存,会使用数据库默认值

Update
方法:int updateByPrimaryKey(T record);
说明:根据主键更新实体全部字段,null值会被更新

方法:int updateByPrimaryKeySelective(T record);
说明:根据主键更新属性不为null的值

Delete
方法:int delete(T record);
说明:根据实体属性作为条件进行删除,查询条件使用等号

方法:int deleteByPrimaryKey(Object key);
说明:根据主键字段进行删除,方法参数必须包含完整的主键属性

Example方法
方法:List selectByExample(Object example);
说明:根据Example条件进行查询 重点:这个查询支持通过Example类指定查询列,通过selectProperties方法指定查询列

方法:int selectCountByExample(Object example);
说明:根据Example条件进行查询总数

方法:int updateByExample(@Param("record") T record, @Param("example") Object example); 说明:根据Example条件更新实体record包含的全部属性,null值会被更新

方法:int updateByExampleSelective(@Param("record") T record, @Param("example") Object example);
说明:根据Example条件更新实体record包含的不是null的属性值

方法:int deleteByExample(Object example);
说明:根据Example条件删除数据

图片.png