Mybatias

Mybatis

目录

1.简介

1丶什么是Mybaties

  • MyBatis 是一款优秀的持久层框架,

  • 它支持自定义 SQL、存储过程以及高级映射。

  • MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。

  • MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

如何获得Mybaties?

  • Maven仓库

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

    中文文档: mybatis – MyBatis 3 | 简介

2丶持久化

数据持久化

  • 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
  • 内存:断电即失
  • 数据库(JDBC),io文件都是持久化

3丶为什么需要mybaties

  • 简单
  • 传统的JDBC代码太过复杂。实现了简化,框架,自动化
  • 优点:
    • 简单易学
    • 灵活
    • sql和代码的分离,提高了可维护性
    • 提供映射标签,支持对象和数据库的orm字段关系映射
    • 提供对象关系映射标签,支持对象关系组建维护
    • 提供xml标签,支持编写动态sql

最重要一点:用的人多

2.第一个mybaties程序:

思路:搭建环境==》导入mybaties ==》编写代码 ==》测试

1丶开发环境

CREATE DATABASE mybaties;
USE mybaties;
CREATE TABLE `user`(
id INT NOT NULL,
`name` VARCHAR(20) NOT NULL,
`pwd` VARCHAR(30) NOT NULL,
PRIMARY KEY (id)
)
INSERT INTO `user` VALUE(1,'六的很','123'),(2,'lc','1234'),(3,'zyj','075');
SELECT * FROM `user`

创建父项目

  1. 创建一个普通的maven项目

  2. 删除src(因为我们不用,这个是父模块,只是用来导依赖的)

  3. 导入依赖(mybatis,mysql,junit)

  4. 设置打包方式为:jar

    <dependencies>
            <!-- mybatis   -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.7</version>
            </dependency>
            <!--    mysql-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.3</version>
            </dependency>
            <!-- junit   -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    

2丶编写mytabis的核心配置文件

<?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"/>
              "jdbc:mysql://localhost:3306/mybaties?characterEncoding=utf-8&amp;serverTimezone=UTC&amp;useSSL=false">
                <property name="username" value="root"/>
                <property name="password" value="123"/>
            </dataSource>
        </environment>
    </environments>
    //引入映射文件
    <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
    </mappers>
</configuration>

3丶编写mapper接口

Mybatis面向接口编程的两个一致:(重)

  • 映射文件的namespace要和mapper接口的全类名保持一致
  • 映射文件中SQL语句的id要和mapper接口的方法名一致

相当于原来的Dao

public interface UserDao {
//    查询
    List<User> getUserList();
    User getUserName(int id);
}

4丶编写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">
<!--命名空间绑定一个DAO/mapper接口-->
<mapper namespace="com.LiuDeHen.mapper.Usermapper">

</mapper>

5丶引入映射文件

 //引入映射文件
    <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
    </mappers>

6丶使用junit测试

    @Test
    public void test() throws IOException {
//        记载核心配置文件
        InputStream resource = Resources.getResourceAsStream("mybatis-config.xml");
//          获取sqlsessionFactoryBuilder
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//        获取sqlsessionFactory
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(resource);
//       获取sqlsession,参数为true就是设置为自动提交事务,一个sqlsession对象就表示和数据库的一次会话
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//        获取mapper接口对象
//        将一个接口丢进去获得一个实例化对象,底层是帮我们实现了接口的实现类,是代理模式
        userMapper mapper = sqlSession.getMapper(userMapper.class);
//        测试功能
        int i = mapper.insertUser();
        if (i>0){
            System.out.println("插入成功");
        }
        //        提交事务
        sqlSession.commit();
    }

7丶加入log4j日志功能

什么是LOG4J?

  • Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件

  • 我们也可以控制每一条日志的输出格式

  • 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程

  • 这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码

  • 添加依赖

    		<dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>
    
  • 添加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/kuang.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
    

8丶封装工具类SqlSessionUtils

public  class SqlSessionUtils {

    public static SqlSession getSqlsession(){
    SqlSession sqlSession=null;
        try {
            InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream);
             sqlSession = build.openSession(true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sqlSession;
    }
}

9丶设置核心配置和映射文件模板

1647651629360

10丶测试增删查改

查询功能的标签必须设置 resultType或者resultMap
resultType:设置默认的映射关系(查询返回来的字段与映射的实体类的属性一致,就赋值)
resultMap:设置自定义的映射关系(属性不一致)

  • mapper接口

    public interface userMapper {
        int insertUser();
        void updateUser();
        void deleteuser();
        user selectID();
        List<user> selectAll();
    }
    
  • mapper.xml

       <!--插入-->
        <insert id="insertUser"  parameterType="com.LiuDeHen.pojo.user">
            insert into mybaties.user values (21,'lc','123');
        </insert>
    
    <!--    void updateUser();-->
        <update id="updateUser">
            update mybaties.user set name='liuchao' where id=21
        </update>
    <!--    void deleteuser();-->
        <delete id="deleteuser">
            delete from mybaties.user where id=1;
        </delete>
    
    <!--    user selectID();-->
    <!--   查询功能的标签必须设置 resultType或者resultMap
                 resultType:设置默认的映射关系(当查询返回来的字段与映射的实体类的属性一致,就赋值)
                 resultMap:设置自定义的映射关系(属性不一致)
     -->
        <select id="selectID" resultType="com.LiuDeHen.pojo.user" >
            select * from mybaties.user where id=2
        </select>
    <!--    List<user> selectAll();-->
        <select id="selectAll" resultType="com.LiuDeHen.pojo.user">
            select * from  mybaties.user;
        </select>
    
  • test测试

   @Test
    public void ces() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream);
        SqlSession sqlSession = build.openSession(true);
        userMapper mapper = sqlSession.getMapper(userMapper.class);
//        以id查询
        user user = mapper.selectID();
        System.out.println(user);
//        查询全部
        List<user> users = mapper.selectAll();
        ListIterator<user> iterator = users.listIterator();
        while (iterator.hasNext()){
            user next = iterator.next();
            System.out.println(next);
        }
//        删除
        mapper.deleteuser();
//        添加
        mapper.insertUser();
//        修改
        mapper.updateUser();
    }

11丶总结:

一下流程:

  1. 首先第一步,就是环境的配置

    1. mysql和mybatis的jar包
    2. 然后写mybatis的xml文件(不要忘了注册),mapper是驱动,也就是我们写的每一个mapper(就是我们原来的操作数据库类,现在是mapper.xml文件),并且绑定上mysql驱动,和我们的数据库(连接数据库)
    3. 到了这里,我们要去编写工具类,根据官方文档。工具类里会根据我们前面的mybatis.xml文件得到一个sqlSessionFactory工厂,使用这个工厂我们可以获取到SqlSession对象(操作sql所有的方法)
    4. 然后我们就需要去写实体类,与数据库要对应
    5. 接下来再写上Dao层的接口和mapper.xml文件(代替原来的Dao实现类),mapper文件绑定id到接口的方法,返回值类型为实体类
  2. 测试

  3. 后面的所有操作都只需要写mapper.xml里的sql语句了,实现了和java代码的解耦,提高维护性

  4. 项目结构

    1647649090755

我们需要了解的三个接口和类

1642555663093

3.配置解析:

1丶配置如下

2丶环境配置(environments)

<environments default="development">
    //default: mybatis可以配置多个environment ,但是一个项目只能用一种,default设置默认的是哪一种
        <environment id="development">
    //type="JDBC/MANAGED"  jdbc:使用原生jdbc的事务管理方式    MANAGED:被管理,例如Spring
            <transactionManager type="JDBC"/>
    //datasource:配置数据源 
            //type:设置数据源的类型   type="POOLED\UNPOOLED\JNDI"
            //POOLED:使用数据库连接池缓存数据库连接
            //UNPOOLED:不使用数据库连接池缓存
            //JNDI:表示使用上下文中的数据源
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybaties?serverTimezone=UTC"/><!--数据库连接-->
                <property name="username" value="root"/>
                <property name="password" value="123"/>
            </dataSource>
        </environment>
    </environments>
  • mybatis可以适应多种环境

  • 但每个SqlSessionFactory实例只能选择一种实例

  • 学会配置多套运行环境,但是一个项目只能运行一个

  • mybatis默认事务管理器是jdbc,

  • dataSource 使用 JDBC 数据源连接对象的资源。 含池的数据源类型:POOLED

3丶属性([properties)

  • 配置文件要按照顺序

    1642570508358

  • mybatis.properties

    //防止重名,可以加个jdbc.的前缀
    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/mybaties?useSSL=false&;characterEncoding=UTF-8&;useUnicode=true&;serverTimezone=GMT
    jdbc.username=root
    jdbc.password=123
    
  • 核心配置文件中声明properties并引入外部地址

    <properties resource="mybatis.properties"/>
    
  • 使用外部配置文件

    <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.username}"/>
                    <property name="password" value="${jdbc.password}"/>
                </dataSource>
    

4丶类型别名(typeAliases)

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

  • 同样要注意标签顺序

    properties?, settings?, typeAliases?, typeHandlers?, objectFactory?,objectWrapperFactory?, reflectorFactory?, plugins?, environments?, databaseIdProvider?, mappers?
    
  • 第一种自定义别名

  • 第二种,以包名下的类起别名(常用)

    <typeAliases>
<!--   自定义     
type:设置需要别名的类型的全类名
alias:设置某个类的别名
别名不区分大小写,如果不写alias就以我们的类名为别名
-->
        <typeAlias type="com.LiuDeHen.pojo.User" alias="User"/>
<!--   以类名
以包下的每个类的类名为别名,也不区分大小写     
-->
        <package name="com.LiuDeHen.pojo"/>
    </typeAliases>
  • 第三种就是注解了

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

    在实体类少的情况下可以用自定义,多就用第二种

5丶设置

  • cacheEnabled 缓存
  • mapUnderscoreToCamelCase 将sql里 字段 index_name 转化为驼峰 indexName
  • 1642573213107

6丶其他配置

7丶映射器(mappers)

在resource下创建包的时候,比如com.LiuDeHen.mapper.xml,这只会是一层目录

要想创建一层一层的包,必须这么创建 com/LiuDeHen/mapper/xml

MapperRegistry:注册绑定我们的Mapper文件

  • 第一种:使用扫描包进行绑定注册包下所有文件

    <mappers>
        <package name="com.LiuDeHen.Dao"/>
    </mappers>
    

    注意点:

    1. 接口和Mapper映射文件必须同名
    2. 接口和Mapper映射文件必须在同一个包下

    1647650234952

    1. 像上图这样,在同一个包下
  • 第二种:resource (推荐使用)进行绑定

    <mappers>
            <mapper resource="com/LiuDeHen/Dao/UserMapper.xml"/>
    </mappers>
    
  • 第三种:class进行绑定

       <mappers>
     <mapper class="com.LiuDeHen.Dao.UserMapper"/>
        </mappers>
    

    注意点:

    1. 接口和Mapper配置文件必须同名
    2. 接口和Mapper配置文件必须在同一个包下

技巧:

如果想将Dao下的Mapper文件放到resource下在resources下建一个和接口所在相同的包,使用 resource 的方式,路径不加resources,对比老师的来如

8丶生命周期和作用域

1642575296684

生命周期和作用域,是至关重要的,因为错误的使用回导致非常严重的并发问题

SqlSessionFactoryBuilder:

  • 一旦创建了 SqlSessionFactory,就不再需要它了
  • 佳作用域是方法作用域(也就是局部方法变量)

SqlSessionFactory:

  • 说白了可以把它当成:数据库连接池
  • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例
  • 最佳作用域是应用作用域
  • 使用单例模式或者静态单例模式

SqlSession:

  • 连接到连接池的一个请求
  • 用完需要关闭,释放池中资源
  • SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域

1642578714005

4.Mybatis获取参数值的两种方式(重点)

  • ${}:本质是jdbc的字符拼接
  • {}本质是jdbc的占位符赋值

  • 记住当需要传入值的名字的时候,形参只是数据,我们最好用@Param注解,标识一个名字,用来调用

1丶mapper接口的方法参数为单个字面量类型

  • 两个都可以获取,且名称任意
<!--       user selectname(String name);-->
    <select id="selectname" resultType="user">
         select * from mybaties.user where name=#{user};   <!--这里的占位符,只是占一个位置,不代表参数名,所以名字任意 -->
        select *from mybaties.user where name='${user}'    <!-- 跟字符串拼接一样需要单引号,同样是任意名称-->
    </select>

2丶mapper接口方法的参数为多个时

  • 此时mybatis会将这些参数放在一个map集合中,以两种方式进行储存

  • arg0,arg1为键,以参数为值

  • param1,param2为键,以参数为值

    <!--       user checkLogin(String name,String pwd);-->
        <select id="checkLogin" resultType="user">
            select * from mybaties.user where name=#{arg0} and pwd=#{arg1};
            select * from mybaties.user where name=#{param1} and pwd=#{param2};
            select * from mybaties.user where name='${param1}' and pwd='${param2}';
            select * from mybaties.user where name='${arg0}' and pwd='${param2}';
        </select>
    

3丶mapper接口方法的参数为多个时,我们使用自己创建的Map

  • 此时name和pwd就是我们自己定义的键

      Map<String, Object> map = new HashMap<>();
            map.put("name","liuchao");
            map.put("pwd","123");
    
<!--    user checkLogin2(Map<String,Object> map);-->
    <select id="checkLogin2" resultType="user">
        select * from mybaties.user where name=#{name} and pwd=#{pwd};
    </select>

4丶mapper接口方法的参数为对象时(常用)

  • 我们知道Map集合会根据传来的Map通过键来找值,那对象同样,是通过属性访问属性值

  • 所以一定要跟对象属性名对应

    <!--     int insertUser2(user u);-->
        <insert id="insertUser2">
            insert into mybaties.user values (#{id},#{name},#{pwd})
        </insert>
    

5丶使用@Param注解命名参数(常用)

  • 第二种方法中,我们的参数会被放到系统的Map里,但是必须使用默认键
  • 第三种方法中,我们使用自定义的Map集合,使用自己定义的Map键
  • 那么@Param注解就是综合两种方法,它会把我们的值放到系统Map里,并使用我们自己定义的键
<!--user checkLogin3(@Param("name") String name,@Param("pwd") String pwd);-->
    <select id="checkLogin3" resultType="user">
        select * from mybaties.user where name=#{name} and pwd=#{pwd}
    </select>
  • @Param源码分析

5.各种查询

1丶查询一条数据时,

  • 可以用对象接收

  • list集合接收

  • 也可以用Map集合接收

    {name=zz, id=5, pwd=123}
    

2丶查询多条数据时

  • 用实体类类型的list集合接收

  • 用Map类型的list集合接收

  • Mybatis为我们设置了默认的类型别名(可以用来查单行单列)

    <!--int selectAll2();-->
        <select id="selectAll2" resultType="java.lang.Integer">
            select COUNT(*) from mybaties.user
        </select>
    
    • 下面这些都是对应的

      1647661029126

3丶当查询返回为map集合时

  • 查询一条

    <!--    Map<String,Object> selectAll3(@Param("id")Integer id);;-->
        <select id="selectAll3" resultType="map">
            select * from mybaties.user where id=#{id}
        </select>
    
  • 查询多条:

    • 第一种
      • 要使用@MapKey这个注解,因为返回的Map只能是一条
      • 使用这个注解,会以注解的value值作为键,把原来的Map作为值,形成一个二位Map输出
    • 第二种
      • 用Map类型的list集合接收
    <!-- @MapKey("name")
        Map<String,Object> selectAll4();
    
     List<Map<String,Object>> selectAll5();
    -->
        <select id="selectAll4" resultType="map">
            select * from mybaties.user
        </select>
    

6.特殊的SQL执行

1丶模糊查询

  • 第一种

    • 使用$,不能使用#,因为会被当成是占位符?拼接到字符串里

      <!-- List<Object> selectName(@Param("name") String name);   -->
          <select id="selectName" resultType="user">
              select * from mybaties.user where name like '${name}%'
          </select>
      
  • 第二种

    • 使用concat拼接字符串

        select * from mybaties.user where name like concat('%',#{name},'%');
      
  • 第三种

     select * from mybaties.user where name like '%'#{name}'%'
    

2丶批量删除

只能用$,因为#占位符接收参数会自动加上单引号 ,而批量删除in()里不能有引号

<!--    int deleteMore(@Param("id") String id);-->
    <delete id="deleteMore">
        delete from mybaties.user where id in(${id})
    </delete>

3丶动态设置表名

同样,只能用$

<!--    List<user> selectMove(@Param("tablename")String tablename); -->
    <select id="selectMove" resultType="user">
        select * from ${tablename}
    </select>

4丶添加功能获取自增的主键

class(class_id,class_name)

student(student_id,student_name,class_id)

  • 可以将有自增主键的的表的主键值
    • 因为原本是自添加,所以我们不要插入id值,自己会有,但是我们插入后,在测试类里是查不到id的
    • 所以可以用这两个属性,设置为后,可以查到id
  • 就可以将这个class_id给另一个表使用
<!--  int insertUser(User2 user2);
useGenerratedkey:设置当前标签中使用了自增主键,
keyProperty:将自增的主键的值 赋给传输映射文件中参数的的某个属性
-->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
    insert into mybaties.user2 values (null,#{name},#{pwd})
</insert>

7.自定义映射resultMap

使用的数据库

create table t_emp(
     eid int  PRIMARY KEY AUTO_INCREMENT not null ,
     emp_name varchar(20),
     age  int,
     sex char,
     email varchar(20),
     did int
);
create table t_dept(
                      did int  PRIMARY KEY AUTO_INCREMENT not null ,
                      dept_name varchar(20)
);
insert into t_emp values (null,'四四',21,'女','21222@qq.com',1);
insert into t_dept values (null,'C');

实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
    private int eid;
    private String empName;
    private Integer age;
    private String sex;
    private String email;
    private Dept dept;
    多对一里,有对象
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dept {
        private int did;
    private String deptname;
    private List<Emp> list;
    一对多里,有集合
}

解决字段名和属性名不一致的问题

1丶为字段起别名,保持和属性名 一致

<!--    List<Emp> selectAll();-->
    <select id="selectAll" resultType="Emp">
        //empname是属性名
        select eid, emp_name as empname, age, sex, email from mybaties.t_emp
    </select>

2丶mapUnderscoreToCamelCase 设置全局配置,将自动映射为驼峰

1647677538442

<settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

3丶使用resultMap

  • resultMap设置自定义映射关系
    • id唯一标识,不能重复
    • type:映射关系中的实体类类型
    • id标签设置主键的映射关系
    • result表示普通属性的映射关系
    • property设置映射关系中的属性名,必须是type属性所设置的实体类中的属性名
    • column设置映射关系中的字段名,必须是sql语句查询出来的字段 名
   <resultMap id="empResultmap" type="emp">  //id就是被调用的名字,type就是映射的实体类
        <id property="id" column="id"/>      //主键映射
        <result property="empName" column="emp_name"/>///:普通属性映射
        <result property="age" column="age"/> //property实体类的属性,column数据库查询出来的字段
        <result property="sex" column="sex"/>		
        <result property="email" column="email"/>
    </resultMap>
<!--    List<Emp> selectAll();-->
    <select id="selectAll" resultMap="empResultmap">  //**调用自己定义的resultMap**
        <!--select eid, emp_name as empname, age, sex, email from mybaties.t_emp-->
        select * from mybaties.t_emp
    </select>

4丶多对一处理

多对一:对应对象

这个案例里就是多个员工对应一个部门

第一种:级联属性赋值
<resultMap id="EmpAndDeptResulymap" type="Emp">
       <id property="eid" column="eid"/>
       <result property="empName" column="emp_name"/>
       <result property="age" column="age"/>
       <result property="sex" column="sex"/>
       <result property="email" column="email"/>
    //dept.did的对象.属性,  将联表查询的did赋值过去
       <result property="dept.did" column="did"/>
       <result property="dept.deptname" column="dept_name"/>
   </resultMap>
<!--   Emp EmpselectDept(@Param("eid") String eid); -->
   <select id="EmpselectDept" resultMap="EmpAndDeptResulymap">
       select * from mybaties.t_emp,mybaties.t_dept
                                   where mybaties.t_dept.did=t_emp.did and eid=#{eid}
   </select>
第二种:association标签
  • association:处理多对一的映射关系
    • javaType:就是属性里多对一的那个一的类型
      • 此时标签里的属性
      • property表示javaType那个类的属性
      • column:同样是sql查出来的字段
<resultMap id="EmpAndDeptResulymapTwo" type="Emp">
        <id property="eid" column="eid"/>
        <result property="empName" column="emp_name"/>
        <result property="age" column="age"/>
        <result property="sex" column="sex"/>
        <result property="email" column="email"/>
        <association property="dept" javaType="Dept">
            <id property="did" column="did"/>
            <result property="deptname" column="dept_name"/>
        </association>
    </resultMap>
<!--   Emp EmpselectDept(@Param("eid") String eid); -->
    <select id="EmpselectDept" resultMap="EmpAndDeptResulymapTwo">
        select * from mybaties.t_emp,mybaties.t_dept
                                    where mybaties.t_dept.did=t_emp.did and eid=#{eid}
    </select>
第三种:分布查询
  • 分布查询

    • 在这个案例里我们多对一,要查询另一个表t_Dept的数据

      • 首先,我们可以先查第一个表t_emp的数据

        • 我们要知道第一个表的实体类,有第二个表的实体类对象,所以肯定要使用resultMap

        • 此时的association的属性介绍

          • property还是type=Emp类的属性
          • select:设置分布查询的唯一标识,是我们另一个表的查询方法的地址(mapper接口全类名.方法名)
          • column:分布查询的条件
             <resultMap id="EmpAndDeptResulymapThree" type="Emp">
                  <id property="eid" column="eid"/>
                  <result property="empName" column="emp_name"/>
                  <result property="age" column="age"/>
                  <result property="sex" column="sex"/>
                  <result property="email" column="email"/>
                  <association property="dept"
                               select="com.LiuDeHen.mapper.DeptMapper.DeptSelect"
                               column="did"
                  >
                  </association>
              </resultMap>
          
          <!--   Emp empSelect(@Param("eid") Integer eid); -->
              <select id="empSelect" resultMap="EmpAndDeptResulymapThree">
                  select * from mybaties.t_emp where eid=#{eid}
              </select>
          
      • 再查第二个表的数据

<!--     Dept DeptSelect(@Param("did") Integer did); -->
    <select id="DeptSelect" resultType="Dept">
        select * from mybaties.t_dept where did=#{did}
    </select>
延迟加载
  • 分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载

    我的版本3.5.7默认为true,所以也可以不用设置

  • aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性加载(3.4版本后,默认为false,所以不需要我们自己设置为false)

  • 此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType="lazy(延迟加载)|eager(立即加载)"

效果

比如我们在查询,两个表其中的一个表中数据的时候(不需要另一个表辅助)

  @Test
    public void DeptselectEmptest(){
        SqlSession sqlsession = SqlSessionUtils.getSqlsession();
        EmpMapper mapper = sqlsession.getMapper(EmpMapper.class);
        Emp emp = mapper.empSelect(2);
        System.out.println(emp.getSex());
    }

开启延迟加载的

1647690065104

没开启的

1647690114170

怎么开启

  • 确保lazyLoadingEnabled为ture
  • 确保aggressiveLazyLoading为false
  • 并且设置 fetchType="lazy"
<association property="dept"
                     select="com.LiuDeHen.mapper.DeptMapper.DeptSelect"
                     column="did"
                     fetchType="lazy"
        >
        </association>

5丶一对多处理

  • 第一种collection处理
    • 标签collection是集合,专门用来处理一对多
      • ofType:表示集合里的数据的类型
  <resultMap id="deptAndEmpResultMap" type="Dept">
        <id property="did" column="did"/>
        <result property="deptname" column="dept_name"/>
        <collection property="list" ofType="Emp">
            <id property="eid" column="eid"/>
            <result property="empName" column="emp_name"/>
            <result property="age" column="age"/>
            <result property="sex" column="sex"/>
            <result property="email" column="email"/>
        </collection>
    </resultMap>
<!--     Dept deptAndEmp(@Param("did") Integer did);-->
    <select id="deptAndEmp" resultMap="deptAndEmpResultMap">
        select * from mybaties.t_dept,mybaties.t_emp
                    where mybaties.t_dept.did=mybaties.t_emp.did and mybaties.t_dept.did=#{did}
    </select>
  • 第二种:分布查询

    • 先查部门表
    • 根据部门did再去查员工表
    • 延迟加载跟多对一一样
    • 多对一和一对多里column条件是一样的,都是联表查询的公共字段
        <resultMap id="deptAndEmpAllResultMap" type="Dept">
            <id property="did" column="did"/>
            <result property="deptname" column="dept_name"/>
            <collection property="list"
                        select="com.LiuDeHen.mapper.EmpMapper.EmpAndDeptAll"
                        column="did"
                        fetchType="lazy"
                />
        </resultMap>
    
    <!--    Dept deptAndEmpAll(@Param("did") Integer did);-->
            <select id="deptAndEmpAll" resultMap="deptAndEmpAllResultMap">
                select * from mybaties.t_dept where did=#{did}
            </select>
    
    <!--     List<Emp> EmpAndDeptAll(@Param("did") Integer did);-->
        <select id="EmpAndDeptAll" resultType="Emp">
            select * from  mybaties.t_emp where did=#{did}
        </select>
    

8.动态sql

什么是动态sql? 根据不同的条件生成不同的sql语句

Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题。

如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

if
where
choose (when, otherwise)
trim (where, set)
foreach
sql

1丶if标签

if :根据标签中test属性所对应的表达式决定标签中的内容是否需要拼接到sQL中

  • 使用标签if
    • 属性test为判断条件
      • 里面的判断内容是用的实体类属性判断,因为是传参是实体类
    • 标签里的内容为 拼接内容
      • 内容格式语法为:字段名=#{属性名}
    • where 1=1 为恒成立条件,当"empName!=null and empName!=''"不成立的时候,直接回去拼接后面age等的,age等前有and拼接关键字,当第一个if不满足就会出现

1647745593230

where后面直接接了and

加了恒等条件后,就不会出现问题

1647745645090

<!--    List<Emp> getdynamicSQL(Emp emp);-->
    <select id="getdynamicSQL" resultType="Emp">
        select * from mybaties.t_emp where 1=1
        <if test="empName!=null and empName!=''">
            emp_name=#{empName}
        </if>
        <if test="age!=null and age!=''">
            and age=#{age}
        </if>
        <if test="sex!=null and sex!=''">
            and sex=#{sex}
        </if>
        <if test="email!=null and email!=''">
            and email=#{email}
        </if>
    </select>

2丶where标签

使用where标签代替关键字

  • 我们上面要用到where 1=1 恒成立等式,避免拼接到and
  • 当有条件成立时,会自动生成where关键字,能帮我们自动去掉前面的and或者or,但是不能省去后的and或者or
  • 当我们所有的条件都不成立时,会帮我们自动去掉where
<!--    List<Emp> getdynamicSQL(Emp emp);-->
    <select id="getdynamicSQL" resultType="Emp">
        select * from mybaties.t_emp
            <where>
        <if test="empName!=null and empName!=''">
            emp_name=#{empName}   <!--and/or 放在后面不能自动去掉-->
        </if>
        <if test="age!=null and age!=''">
            or age=#{age}
        </if>
        <if test="sex!=null and sex!=''">
            and sex=#{sex}
        </if>
        <if test="email!=null and email!=''">
            and email=#{email}
        </if>
            </where>
    </select>

3丶trim标签

  • trim
    • prefix="" suffix="" :在trim标签内容 前后添加指定内容
    • prefixOverrides="" suffixOverrides="" : 在trim标签中内容前后去掉指定内容
    • 像where一样,如果trim标签的内容都不成立,trim就不会生效
    • 它可以做到去掉后面的and或者or
<!--    List<Emp> getdynamicSQL(Emp emp);-->
    <select id="getdynamicSQL" resultType="Emp">
        select * from mybaties.t_emp
      <trim suffix="" prefix="where" suffixOverrides="and|or" prefixOverrides="">
        <if test="empName!=null and empName!=''">
            emp_name=#{empName} and
        </if>
        <if test="age!=null and age!=''">
            age=#{age}  or
        </if>
        <if test="sex!=null and sex!=''">
            sex=#{sex}  and
        </if>
        <if test="email!=null and email!=''">
             email=#{email}  and
        </if>
      </trim>
    </select>

4丶choose when otherwise

  • 相当于java的switch case default
  • when最少有一个,otherwise最多有一个
<!--    List<Emp> getdynamicSQL(Emp emp);-->
    <select id="getdynamicSQL" resultType="Emp">
        select * from mybaties.t_emp
        where
        <choose>
            <when test="empName!=null and empName!=''">
             emp_name=#{empName}
            </when>
            <when test="age !=null and age!=''">
             age=#{age}
            </when>
            <when test="sex !=null and sex!=''">
             sex=#{sex}
            </when>
            <when test="email !=null and email!=''">
                email=#{email}
            </when>
            <otherwise>
                did=1
            </otherwise>
        </choose>
    </select>

5.foreach

实现批量删除
  • foreach标签
    • collection:遍历的是哪一个集合/数组
    • item:遍历的数组/集合中的每一个数据
    • open:foreach标签所循环的所有内容的开始符
    • close:foreach标签所循环的所有内容的结束符
    • separator:每一个数据中间用什么隔开

第一种使用 in

<!--    int deleteMoreSQL(@Param("eids") Integer []eid);-->
    <delete id="deleteMoreSQL">
        delete from mybaties.t_emp where eid in
        <foreach collection="eids" item="e" open="(" close=")" separator=",">
            #{e}
        </foreach>
    </delete>

第二种使用or

   <!--    int deleteMoreSQL(@Param("eids") Integer []eid);-->
    <delete id="deleteMoreSQL">
        delete from mybaties.t_emp where eid=
        <foreach collection="eids" item="e" separator="or">
            #{e}
        </foreach>
    </delete>

sql拼接效果:

delete from mybaties.t_emp where eid in ( ? , ? , ? )

delete from mybaties.t_emp where eid= ? or ? or ?

实现批量添加
<!--    int insertMoreSQL(@Param("emps") List<Emp> emps);-->
    <insert id="insertMoreSQL">
        insert into mybaties.t_emp values
        <foreach collection="emps" item="emp" separator=",">
            (null,#{emp.empName},#{emp.age},#{emp.sex},#{emp.email},null)
        </foreach>
    </insert>

sql拼接效果:

insert into mybaties.t_emp values (null,?,?,?,?,null) , (null,?,?,?,?,null) , (null,?,?,?,?,null)

6丶SQL片段

设置sql片段 :标签

<sql id="empSQL">eid,emp_name,age, sex, email</sql>

引用片段 :标签

 select <include refid="empSQL"></include> from mybaties.t_emp

9.分页查询

为什么需要分页?

  • 减少数据的处理量

使用limit分页

select * from 表名  limit  indexstart  rows     indexstart:起始行数  rows:多少行

使用mybatis实现分页

  • 接口

    //    分页查询
        List<User> getLimit(Map<String,Object> map);
    
  • mapper文件

    对应的resultMap解决字段和属性不一样    
    <resultMap id="UserMap" type="User">
    <!-- column对应着数据库的字段,property对应着实体类的属性       -->
            <result column="pwd" property="password"/>
    </resultMap>
    
    <select id="getLimit" resultMap="UserMap" parameterType="map">
            select * from  mybaties.user limit #{start},#{rows};
    </select>
    
  • 测试

    @Test
        public void testLimit(){
            SqlSession sqlSession = MybatisUtils.getsqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            HashMap<String, Object> hashMap = new HashMap<String, Object>();
            hashMap.put("start",0);
            hashMap.put("rows",3);
            List<User> limit = mapper.getLimit(hashMap);
            for (User user : limit) {
                System.out.println(user);
            }
            sqlSession.close();
        }
    

10.使用注解开发

  1. 在接口中使用注解

     @Select("select id,name,pwd as password from mybaties.User")
        List<User> getUser();
    
  2. 在核心配置文件中绑定接口

    <mappers>
            <mapper class="com.LiuDeHen.Dao.UserMapper"/>
    </mappers>
    
  3. 测试

    @Test
        public void test() {
            SqlSession sqlSession = MybatisUtils.getsqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List<User> user = mapper.getUser();
            for (User user1 : user) {
                System.out.println(user1);
            }
            sqlSession.close();
        }
    

    本质:反射机制

    底层:动态代理

9.mybaitis流程基本梳理

  • 首先我们在使用时,会调用工具类MybatisUtils

    1. 里面有一个resource路径是我们的全局核心配置文件

    2. 然后会获取一个流,并将这个流传给build方法

    3. 这个build方法里有个构造器XMLConfigBuilder(),它会将流里(核心配置文件里)的环境等传进去,返回得到一个sqlSessionFactory工厂

      1642734589849

    4. 通过工厂获取SqlSession实现crud操作sql

    5. SqlSession可以通过getMapper方法再使用反射动态获取是哪一个接口

11.使用注解实现增删查改

//使用注解增删改查
public interface UserMapper {
    @Select("select id,name,pwd as password from mybaties.User")
    List<User> getUser();
    @Select("select * from mybaties.User where id=#{id}")
    User getUserID(@Param("id") int id);

    @Insert("insert into mybaties.user values(#{id},#{name},#{pwd})")
    int getInsert(User user);

    @Update("update mybaties.User set name=#{name} where id=#{id}")
    int getUpdate(User user);

    @Delete("delete from mybaties.User where id=#{id}")
    int getDelete(@Param("id") int id);
    
    
    
//测试:
	public void test() {
        SqlSession sqlSession = MybatisUtils.getsqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> user = mapper.getUser();
        for (User user1 : user) {
            System.out.println(user1);
        }
        sqlSession.close();
    }
    @Test
    public void testId(){
        SqlSession sqlSession = MybatisUtils.getsqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.getUserID(1);
        System.out.println(user);
        sqlSession.close();
    }

    @Test
    public void testInsert(){
        SqlSession sqlSession = MybatisUtils.getsqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int zz = mapper.getInsert(new User(6, "zz", "222"));
        if (zz>0){
            System.out.println("插入成功");
        }
        sqlSession.close();
    }

    @Test
    public void testUpdate(){
        SqlSession sqlSession = MybatisUtils.getsqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int zz = mapper.getUpdate(new User(6, "lc",""));
        if (zz>0){
            System.out.println("修改成功");
        }
        sqlSession.close();
    }
    @Test
    public void testDelet(){
        SqlSession sqlSession = MybatisUtils.getsqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int zz = mapper.getDelete(3);
        if (zz>0){
            System.out.println("删除成功");
        }
        sqlSession.close();
    }

注意在使用工厂回去sqlsession时,将option设置成true,就能dml事务自动提交

  return sqlSessionFactory.openSession(true);

12.lombok

可以简化实体类得代码

使用步骤

  1. 安装插件

  2. 项目导入jar包

  3. 在实体类上加注解

    @Getter and @setter
    @Fie1dNameConstants
    @Tostring
    @EqualsAndHashcode
    
    

13.缓存

1丶一级缓存

范围:一个sqlsssion会话

一级缓存是SqlSession级别的通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问
使一级缓存失效的四种情况:

  • 1)不同的SqlSession对应不同的一级缓存

  • 2)同一个SqlSession但是查询条件不同

  • 3)同一个SqlSession两次查询期间执行了任何一次增删改操作

  • 4)同一个SqlSession两次查询期间手动清空了缓存

2丶二级缓存

范围:SqlSessionFactory创建的所有sqlsession

二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取
二级缓存开启的条件:

  • a>在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置

  • b>在映射文件中设置标签

  • c>二级缓存必须在SqlSession关闭或提交之后有效

  • d>查询的数据所转换的实体类类型必须实现序列化的接口

  • 使二级缓存失效的情况:

  • 两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效

3丶二级缓存的配置

在mapper配置文件中添加的cache标签可以设置一些属性:.

  • eviction属性:缓存回收策略

    LRU (Least Recently Used)-最近最少使用的:移除最长时间不被使用的对象。

​ FIFO (First in First out)-先进先出:按对象进入缓存的顺序来移除它们。

​ SOFT-软引用:移除基于垃圾回收器状态和软引用规则的对象。

​ WEAK-弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

​ 默认的是 LRU。

  • flushlnterval属性:刷新间隔,单位毫秒

    默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新

  • size属性:引用数目,正整数
    代表缓存最多可以存储多少个对象,太大容易导致内存溢出.

  • readOnly属性:只读,true/false
    true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。

false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。

4丶缓存查询的顺序

  • 先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用。

  • 如果二级缓存没有命中,再查询一级缓存

  • 如果一级缓存也没有命中,则查询数据库

  • SqlSession关闭之后,一级缓存中的数据会写入二级缓存

14.mybatis逆向工程

  • 正向工程:先创建Java实体类,由框架负责根据实体类生成数据库表。Hibernate是支持正向工程的

  • 逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成如下资源:

  • Java实体类

    • Mapper接口

    • Mapper映射文件

创建逆向工程的步骤

添加依赖和插件
    <dependencies>
        <!-- MyBatis核心依赖包 -->
        <!-- mybatis   -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>
        <!--    mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.3</version>
        </dependency>
        <!-- junit   -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- log4j日志 -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>
    <!-- 控制Maven在构建过程中相关配置 -->
    <build>
        <!-- 构建过程中用到的插件 -->
        <plugins>
            <!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.0</version>
                <!-- 插件的依赖 -->
                <dependencies>
                    <!-- 逆向工程的核心依赖 -->
                    <dependency>
                        <groupId>org.mybatis.generator</groupId>
                        <artifactId>mybatis-generator-core</artifactId>
                        <version>1.3.2</version>
                    </dependency>
                    <!-- 数据库连接池 -->
                    <dependency>
                        <groupId>com.mchange</groupId>
                        <artifactId>c3p0</artifactId>
                        <version>0.9.2</version>
                    </dependency>
                      <!--    mysql-->
                            <dependency>
                                <groupId>mysql</groupId>
                                <artifactId>mysql-connector-java</artifactId>
                                <version>5.1.3</version>
                            </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>

创建逆向工程的配置文件

文件名必须是:generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <!--
    targetRuntime: 执行生成的逆向工程的版本
    MyBatis3Simple: 生成基本的CRUD(清新简洁版)
    MyBatis3: 生成带条件的CRUD(奢华尊享版)
    -->
    <context id="DB2Tables" targetRuntime="MyBatis3Simple">
        <!-- 数据库的连接信息 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/mybaties"
                        userId="root"
                        password="123">
        </jdbcConnection>
        <!-- javaBean的生成策略  pojo-->
        <javaModelGenerator targetPackage="com.LiuDeHen.pojo" targetProject=".\src\main\java">
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
        <!-- SQL映射文件的生成策略   mapper.xml-->
        <sqlMapGenerator targetPackage="com.LiuDeHen.mapper"
                         targetProject=".\src\main\resources">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>
        <!-- Mapper接口的生成策略   mapper-->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.LiuDeHen.mapper" targetProject=".\src\main\java">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>
        <!-- 逆向分析的表 -->
        <!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName -->
        <!-- domainObjectName属性指定生成出来的实体类的类名 -->
        <table tableName="t_emp" domainObjectName="Emp"/>
        <table tableName="t_dept" domainObjectName="Dept"/>
    </context>
</generatorConfiguration>
创建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>
    <properties resource="jdbc.properties"/>

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

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <package name="com.LiuDeHen.mapper"/>
    </mappers>
</configuration>
执行MBG插件的generate目标

1647775739263

注意事项:mysql的依赖要和逆向工程插件的mysql依赖版本一样

QBC

查询
  • selectByExample:按条件查询,需要传入一个example对象或者null;如果传入一个null,则表示没有条件,也就是查询所有数据

  • example.createCriteria().xxx:创建条件对象,通过andXXX方法为SQL添加查询添加,每个条件之间是and关系

  • example.or().xxx:将之前添加的条件通过or拼接其他条件

增改
  • updateByPrimaryKey:通过主键进行数据修改,如果某一个值为null,也会将对应的字段改为null

  • mapper.updateByPrimaryKey(new Emp(1,"admin",22,null,"456@qq.com",3));

  • updateByPrimaryKeySelective():通过主键进行选择性数据修改,如果某个值为null,则不修改这个字段

  • `mapper.updateByPrimaryKeySelective(new Emp(2,"admin2",22,null,"456@qq.com",3));

15.分页插件

开启分页功能

  • 在查询功能之前使用PageHelper.startPage(int pageNum, int pageSize)开启分页功能
  • pageNum:当前页的页码
    • pageSize:每页显示的条数
@Test
public void testPageHelper() throws IOException {
	InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
	SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
	SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
	SqlSession sqlSession = sqlSessionFactory.openSession(true);
	EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
	//访问第一页,每页四条数据
	PageHelper.startPage(1,4);
	List<Emp> emps = mapper.selectByExample(null);
	emps.forEach(System.out::println);
}

分页相关数据

方法一:直接输出
@Test
public void testPageHelper() throws IOException {
	InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
	SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
	SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
	SqlSession sqlSession = sqlSessionFactory.openSession(true);
	EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
	//访问第一页,每页四条数据
	Page<Object> page = PageHelper.startPage(1, 4);
	List<Emp> emps = mapper.selectByExample(null);
	//在查询到List集合后,打印分页数据
	System.out.println(page);
}
  • 分页相关数据:

    Page{count=true, pageNum=1, pageSize=4, startRow=0, endRow=4, total=8, pages=2, reasonable=false, pageSizeZero=false}[Emp{eid=1, empName='admin', age=22, sex='男', email='456@qq.com', did=3}, Emp{eid=2, empName='admin2', age=22, sex='男', email='456@qq.com', did=3}, Emp{eid=3, empName='王五', age=12, sex='女', email='123@qq.com', did=3}, Emp{eid=4, empName='赵六', age=32, sex='男', email='123@qq.com', did=1}]
    
方法二使用PageInfo
  • 在查询获取list集合之后,使用PageInfo<T> pageInfo = new PageInfo<>(List<T> list, intnavigatePages)获取分页相关数据
  • list:分页之后的数据
    • navigatePages:导航分页的页码数
@Test
public void testPageHelper() throws IOException {
	InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
	SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
	SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
	SqlSession sqlSession = sqlSessionFactory.openSession(true);
	EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
	PageHelper.startPage(1, 4);
	List<Emp> emps = mapper.selectByExample(null);
	PageInfo<Emp> page = new PageInfo<>(emps,5);
	System.out.println(page);
}
  • 分页相关数据:

    PageInfo{
    pageNum=1, pageSize=4, size=4, startRow=1, endRow=4, total=8, pages=2, 
    list=Page{count=true, pageNum=1, pageSize=4, startRow=0, endRow=4, total=8, pages=2, reasonable=false, pageSizeZero=false}[Emp{eid=1, empName='admin', age=22, sex='男', email='456@qq.com', did=3}, Emp{eid=2, empName='admin2', age=22, sex='男', email='456@qq.com', did=3}, Emp{eid=3, empName='王五', age=12, sex='女', email='123@qq.com', did=3}, Emp{eid=4, empName='赵六', age=32, sex='男', email='123@qq.com', did=1}], 
    prePage=0, nextPage=2, isFirstPage=true, isLastPage=false, hasPreviousPage=false, hasNextPage=true, navigatePages=5, navigateFirstPage=1, navigateLastPage=2, navigatepageNums=[1, 2]}
    
  • 其中list中的数据等同于方法一中直接输出的page数据

常用数据:

  • pageNum:当前页的页码
  • pageSize:每页显示的条数
  • size:当前页显示的真实条数
  • total:总记录数
  • pages:总页数
  • prePage:上一页的页码
  • nextPage:下一页的页码
  • isFirstPage/isLastPage:是否为第一页/最后一页
  • hasPreviousPage/hasNextPage:是否存在上一页/下一页
  • navigatePages:导航分页的页码数
  • navigatepageNums:导航分页的页码,[1,2,3,4,5]
posted @   又菜又ai  阅读(56)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示