学习SSM的记录(五)-- MyBatis

目录

MyBatis简介

持久层框架对比

案例演示

ibatis与Mybatis

MyBatis基本使用

mybatis事务

mybatis配置文件下的标签必须严格按照顺序编写:

1.日志输出

2.数据输入

2.1 单个简单类型参数

2.2 实体类类型参数

2.3 多个简单类型参数

2.4 Map类型参数

3.数据输出

3.1 返回单个简单类型

3.2 返回实体类对象

3.3 返回Map类型

3.4 返回List类型

3.5 返回主键值

*3.6 实体类属性和数据库字段对应关系

驼峰映射

MyBatis多表映射

多表映射

对一映射

样例演示:

对多映射

样例演示:

多表映射的注意点(推荐点)

MyBatis动态语句

if 和 where 标签

set标签

trim标签(了解)

choose/when/otherwise标签

foreach标签(重点)

sql片段

MyBatis高级拓展

Mapper批量映射优化

插件和分页插件PageHelper

PageHelper插件

逆向工程和MybatisX插件

orm思维持久层框架

逆向工程插件MybatisX插件


  • SSM为SpringFramework + SpringMVC + MyBatis
  • Spring的3大特性:IoC(控制反转),DI(依赖注入),AOP(面向切面编程)。
  • 框架 = jar + 配置文件

MyBatis简介

简单来说,MyBatis是一款持久层框架,它可以简化我们对数据库的操作,它通过简单的XML或注解将原始类型、接口和Java的pojo类配置和映射为数据库中的数据。

MyBatis早期叫做iBatis,到iBatis3.x正式更名为MyBatis,因此在导依赖时可能会出现该单词。

本文章使用的MyBatis版本为3.5.11。

持久层框架对比

JDBC:

  • 代码繁琐,耦合度高,不易维护。

Hibernate 和 JPA:

  • 操作简单、开发效率高。
  • 较复杂的sql需要绕过该框架。
  • 内部生成的sql不容易优化。
  • pojo中如果字段较多难以部分映射,数据库性能下降。

MyBatis:

  • 轻量级,性能优秀。
  • sql 和 java编码分开,功能边界清晰。java代码主业务,sql语句专注数据。
  • 开发效率可以接受。

案例演示

1.创建数据库和表并添加数据。

create database mybatis_example;

use mybatis_example;

create table t_emp(

        emp_id int auto_increment,

        emp_name char(20),

        emp_salary double(10,5),

        primary key(emp_id)

);

insert into t_emp(emp_name,emp_salary) values ('tom',200.00),('jerry',666.66),('andy',777.77);

2.创建spring-mybatis项目并导入以下依赖。

    <dependencies>
<!--        mybatis依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.11</version>
        </dependency>
<!--        mysql驱动,mybatis底层需要jdbc驱动,mybatis自带连接池-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>
<!--        junit5依赖-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.3.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

3.编写一个pojo类employee,包含以下属性

private Integer empId;

private String empName;

private Double empSalary;

4.编写Mapper层(数据访问层)接口:EmployeeMapper

public interface EmployeeMapper {
    Employee queryById(Integer id);
}

5.在resources下创建EmployeeMapper.xml(一般与上方接口相同),以下为mybatis的xml固定的约束

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

6.编写EmployeeMapper.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--    namespace = mapper对应接口的全限定符-->
<mapper namespace="com.qiu.mapper.EmployeeMapper">
<!--    每一个<curd>标签都对应一个方法
        id值对应方法名,resultType对应返回类型
        注意:mapper接口不能重载。
-->
    <select id="queryById" resultType="com.qiu.pojo.Employee">
        select emp_id empId,emp_name empName,emp_salary empSalary
        from t_emp where emp_id=${id};
    </select>
</mapper>

7.创建并编写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">
<!--    以上为mybatis配置文件的约束-->
<configuration>

    <!-- environments表示配置Mybatis的开发环境,可以配置多个环境,在众多具体环境中,使用default属性指定实际运行时使用的环境。default属性的取值是environment标签的id属性的值。 -->
    <environments default="development">
        <!-- environment表示配置Mybatis的一个具体的环境 -->
        <environment id="development">
            <!-- Mybatis的内置的事务管理器 -->
            <transactionManager type="JDBC"/>
            <!-- 配置数据源 -->
            <dataSource type="POOLED">
                <!-- 建立数据库连接的具体信息 -->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis_example"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!-- Mapper注册:指定Mybatis映射文件的具体位置 -->
        <!-- mapper标签:配置一个具体的Mapper映射文件 -->
        <!-- resource属性:指定Mapper映射文件的实际存储位置,这里需要使用一个以类路径根目录为基准的相对路径 -->
        <!--    对Maven工程的目录结构来说,resources目录下的内容会直接放入类路径,所以这里我们可以以resources目录为基准 -->
        <mapper resource="mappers/EmployeeMapper.xml"/>
    </mappers>

</configuration>

8.测试方法

public class MybatisTest {


    @Test
    public void testSelectEmployee() throws IOException, IOException, IOException {

        // 1.创建SqlSessionFactory对象
        // ①声明Mybatis全局配置文件的路径
        String mybatisConfigFilePath = "mybatis-config.xml";

        // ②以输入流的形式加载Mybatis配置文件
        InputStream inputStream = Resources.getResourceAsStream(mybatisConfigFilePath);

        // ③基于读取Mybatis配置文件的输入流创建SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // 2.使用SqlSessionFactory对象开启一个会话
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 3.根据EmployeeMapper接口的Class对象获取Mapper接口类型的对象(动态代理技术)
        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);

        // 4. 调用代理类方法既可以触发对应的SQL语句
        Employee employee = mapper.queryById(1);

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

        // 4.关闭SqlSession
        sqlSession.commit(); //提交事务 [DQL不需要,其他需要]
        sqlSession.close(); //关闭会话

    }

}

9.执行后输出如下:

employee = Employee{id=1, empName='tom', empSalary=200.0}

数据访问层之前叫Dao层,在mybatis中更偏向于叫做Mapper。

  • 之前的实现方式为:
    • XxxDao 接口 规定方法
    • XxxDaoImpl 实现类 方法的具体实现(操作数据库)
  • mybatis的实现方法为:
    • XxxMapper 接口 规定方法,
    • 但具体的实现有两种方式:
      • XML方式:XxxMapper.xml 在xml中写接口对应方法的sql语句。
      • 注解方式:不常用。

ibatis与Mybatis

Mybatis对数据库的curd是对ibatis功能的封装和优化

MyBatis基本使用

mybatis事务

当获取mybatis的SqlSession对象时使用SqlSessionFactory对象的openSession()获取的,会自动开启事务,但不会自动提交事务,需要使用Session对象的commit()方法手动提交。

可以使用SqlSessionFactory对象的openSession(true)方法获取Session对象,该对象会自动提交事务。

mybatis配置文件下的标签必须严格按照顺序编写:

  • configuration(配置)
    • properties(属性)
    • settings(设置)
    • typeAliases(类型别名)
    • typeHandlers(类型处理器)
    • objectFactory(对象工厂)
    • plugins(插件)
    • environments(环境配置)
    • environment(环境变量)
    • transactionManager(事务管理器)
    • dataSource(数据源)
    • databaseIdProvider(数据库厂商标识)
    • mappers(映射器)

1.日志输出

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

可以设置的值有:SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING。

2.数据输入

  • 在xml中sql语句的参数是可以使用${}或#{}传入的
    • 如:
      <select id="queryById" resultType="com.qiu.pojo.Employee">
          select * from t_emp where emp_id=${id}(或者#{id});
      </select>
    • ${}:将直接把参数使用字符串拼接与sql语句拼接在一起
    • #{}:将先使用 ? 占位符来把sql语句完成,在往占位符中赋值。可以防止【注入攻击】
    • 推荐:当参数是数据值是使用#{},否则使用${}。(如:select * from t_emp where ${find}=#{id})
  • 传入的数据类型:
    • 简单类型:简单来说就是在传入的数据中只能得到一个值。如:
      • 基本数据类型:int,byte,short…
      • 基本数据类型的包装类:Integer,Character,Double…
      • 字符串类型:String…
    • 复杂类型:可以在传入的数据中得到多个值。如:
      • 实体类:Employee,Student…
      • 集合类型:List,Set,Map…
      • 数组类型:int[]…
      • 复合类型:List<Employee>,实体类中包含数组…
2.1 单个简单类型参数

在EmployeeMapper接口编写方法:

int deteleById(Integer id);

List<Employee> queryBySalary(Double salary);

在EmployeeMapper.xml文件编写sql语句:

<!--    传入单个简单类型时,#{key}或${key} 中 key 随便写,但一般写参数名-->
    <delete id="deleteById">
        delete from t_emp where emp_id = #{id};
    </delete>
<!--    返回值类似List<实体类>时,返回参数依然为实体类的全限定符-->
    <select id="queryBySalary" resultType="com.qiu.pojo.Employee">
        select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_salary = #{salary};
    </select>
2.2 实体类类型参数

接口方法:

int insertEmp(Employee employee);

xml文件的sql语句:

<!--    传入实体类类型时,#{key}或${key} 中 key 写实体类的属性名-->
    <insert id="insertEmp">
        insert into t_emp (emp_name,emp_salary) values (#{empName},#{empSalary});
    </insert>
2.3 多个简单类型参数

接口方法:

List<Employee> queryByNameAndSalary(String name,Double salary);

方法1:

在接口方法的参数前加上@Param("name")注解来指定名称再到sql语句下传入:

List<Employee> queryByNameAndSalary(@Param("a") String name,@Param("b") Double salary);
<select id="queryByNameAndSalary" resultType="com.qiu.pojo.Employee">
    select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_name = #{a} emp_salary = #{b};
</select>

方式2:Mybatis默认机制会把参数按顺序设置为arg0,arg1…或param1,param2…。

        select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_name = #{param1} emp_salary = #{param2};
        select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_name = #{arg0} emp_salary = #{arg1};

2.4 Map类型参数
传入Map类型时,#{key}或${key} 中 key 写Map中对应的key

3.数据输出

数据输出主要有两种:

  • 增删改操作所影响到的行数:直接使用int或long接收
  • 查询语句的查询结果
  • 插入时可能需要主键回显

类型别名:

  • 可以将Java类型缩写。
  • Mybatis为一些常用的Java类型设置了简写:
    • 基本数据类型:int double --> _int _double(前面加下划线)
    • 包装数据类型:Integer Double ->int integer double
    • 集合容器类型:Map List HashMap -> 小写即可 map list hashmap

如果Mybatis没有设置的类型,可以在Mybatis配置文件下自己设置别名或直接写全限定符:

    <typeAliases>
<!--        直接设置类型别名-->
        <typeAlias type="com.qiu.pojo.Employee" alias="employee"/>
<!--        设置包别名,默认会把包下的Java Bean下的首字母小写作为它的别名-->
        <package name="com.qiu.pojo"/>
    </typeAliases>

resultType语法:

  • 类的全限定符号
  • 别名简称
3.1 返回单个简单类型

接口方法:

//如果是增删改语句直接使用int或long
int delectById(Integer id);
//查询语句
String queryNameById(Integer id);
Double querySalaryById(Integer id);

xml文件sql语句:

<delete id="deleteById">
    delete from t_emp where emp_id = #{id}
</delete>

<select id="queryNameById" resultType="java.lang.String">
    select emp_name from t_emp where emp_id = #{id}
</select>

<select id="querySalaryeById" resultType="double">
    select emp_salary from t_emp where emp_id = #{id}
</select>
3.2 返回实体类对象

接口方法:

Employee queryById(Integer id);

xml文件sql语句:

<select id="queryById" resultType="com.qiu.pojo.Employee">
    select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_id = #{id};
</select>
3.3 返回Map类型

接口方法:

Map<String,Object> selectEmpNameAndMaxSalary();

xml文件sql语句:

<select id="selectEmpNameAndMaxSalary" resultType="map">
    select
        emp_name 员工姓名,
        emp_salary 员工工资,
        (select AVG(emp_salary) from t_emp) 部门平均工资
    from t_emp where emp_salary = (select MAX(emp_salary) from t_emp);
</select>

有实体类时用实体类,没有时使用map。

3.4 返回List类型

返回值是集合,resultType不需要指定集合类型,只需要指定泛型。

接口方法:

List<Employee> queryAll();

xml文件sql语句:

<select id="queryAll" resultType="com.qiu.pojo.Employee">
    select * from t_emp;
</select>
3.5 返回主键值

1.自增长类型主键

sql语句

<insert id="insertEmp" useGeneratedKeys="true" keyColumn="emp_id" keyProperty="empId">
    insert into t_emp (emp_name, emp_salary)
    values (#{empName},#{empSalary});
</insert>

测试代码:

……
Employee employee = new Employee();
employee.setEmpName("刘德华");
employee.setEmpSalary(1999.99);
mapper.insertEmp(employee);
System.out.println("row = " + employee.getId());
……

2.非自增长类型主键

主键为字符串类型,可以自己维护,即自己在插入数据时自己来写它的主键。

也可以让mybatis帮我们维护:

<!--
    <selectKey>标签可以在插入之前还是之后执行一段sql语句
    order="BEFORE"或"AFTER" 表示在该sql是在插入语句执行前还是执行后执行
    resultType 返回值类型,可以用别名
    keyProperty 返回结果给哪个属性赋值
-->
<insert id="insertTeacher">
    <selectKey order="BEFORE" resultType="string" keyProperty="tId">
        <!--获取一个UUID并把里面的'-'去掉-->
        select REPLACE(UUID(),'-','');
    </selectKey>
    insert into teacher (t_id,t_name) values (#{tId},#{tName});
</insert>
*3.6 实体类属性和数据库字段对应关系

如果实体类的名与数据表的列名不一致的时候,可以:

方案1.起别名 select t_id tId, t_name tName from teacher where t_id = #{tId};

方案2.开启驼峰映射:t_id =>tId,t_name =>tName

方案3.resultMap标签:(在select标签中resultMap和resultType只能二选一)

resultType只有在开启驼峰映射时才会按照规则自动映射,而且只能映射一层结构。深层次的对象结构无法映射,多表查询的时候结果无法映射。

Order                                        数据库 

        orderId                                        order_id

        orderName                                  order_name

        OrderItem orderItem

                                 itemId                        item_id        ----->这两个不会映射

resultMap自定义映射:

<!--
    resultMap的id标识 对应 <select>标签的resultMap=“id”,type标识 具体返回类型:全限定符或别名,集合只写泛型。
        <id>标签 对应 主键映射关系
        <result>标签 对应 普通列的映射关系
-->
<resultMap id="tMap" type="teacher">
    <id column="t_id" property="tId"/>
    <result column="t_name" property="tName"/>
</resultMap>
<select id="queryById" resultMap="tMap">
    select t_id,t_name
    from teacher where t_id = #{tId};
</select>

驼峰映射

在获取数据时,数据库的字段一般使用下滑线,JavaBean一般使用驼峰命名法,每次写sql都要在sql语句中起别名太麻烦。但MyBatis可以设置驼峰映射:emp_id ->empId。

在MyBatis配置文件中设置settings:

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

开启后SQL语句可以简化:

<select id="queryById" resultType="com.qiu.pojo.Employee">
    select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_id = #{id};
</select>

简化后:

<select id="queryById" resultType="com.qiu.pojo.Employee">
    select * from t_emp where emp_id = #{id};
</select>

MyBatis多表映射

多表映射

当需要多表联查时,我们不会总有对应的实体类,因此需要进行多表映射。

  • 1.定义sql语句
  • 2.设计存储数据的实体类
  • 3.指定查询返回的结果
  • 4.自己定义结果集映射(字段->属性)(resultMap)

对一映射

对一关系:夫妻一方对应一方,一个订单对应一个客户。

实体类设计:对一关系下,类中只要包含单个对方对象类型属性即可。如:

public class Customer {
    private Integer customerId;
    private String customerName;
}
public class Order {
    private Integer orderId;
    private String orderName;
    private Customer customer;//一份订单对应一个客户
}
样例演示:

业务:在数据库的order表和customer表中查找到order_id为1 的 订单信息和对应的客户信息。

 1.创建数据库表并插入数据

2.不考虑多表查询的创建与数据库表对应的实体类

3.考虑到业务需要,在Order类中加入Customer来获取查找到的数据的customer信息

4.在mapper接口中添加业务方法

5.设计sql语句

当id = 1时结果为:

这里tor.customer_id 和 tur.customer_id在执行时只会返回customer_id

6.在mapper.xml中编写sql语句

    <resultMap id="orderMap" type="order"><!--id:要传入sel标签中的resultMap type:返回类型,此处使用别名-->
        <id column="order_id" property="orderId"/>
        <result column="order_name" property="orderName"/>
        <result column="customer_id" property="customerId"/>
<!--        association标签作用是对一时给单个对象赋值
            property:在主类型中次类型的属性名,
            javaType:次类型的类型,此处为别名-->
        <association property="customer" javaType="customer">
            <id column="customer_id" property="customerId"/>
            <result column="customer_name" property="customerName"/>
        </association>
    </resultMap>

    <select id="queryOrderById" resultMap="orderMap">
        select *
        from t_order tor
            join t_customer tur
                on tor.customer_id = tur.customer_id
        where tor.order_id = #{id};
    </select>

7.编写测试代码并执行

执行结果:

对多映射

对多关系:一个客户可以有多份订单,一个导师可以有多个学员。

实体类设计:对多关系下,类中只要包含对方类型集合属性即可。如:

public class Order {
    private Integer orderId;
    private String orderName;
    private Customer customer;//一份订单对应一个客户
}
public class Customer {
    private Integer customerId;
    private String customerName;
    private List<Order> orderList;//一个客户有多份订单
}
样例演示:

业务:在数据库的order表和customer表中查找到customer_id为1 的 客户信息和对应的所有订单信息。

  1.创建数据库表并插入数据

2.不考虑多表查询的创建与数据库表对应的实体类

3.考虑到业务需要,在Customer类中加入List<Order>来获取查找到的数据中的多个order信息

4.在mapper接口中添加业务方法

5.设计sql语句

当id = 1时结果为:

这里tor.customer_id 和 tur.customer_id在执行时只会返回customer_id

6.在mapper.xml中编写sql语句

    <resultMap id="customerMap" type="customer">
        <id column="customer_id" property="customerId"/>
        <result column="customer_name" property="customerName"/>
<!--        collection标签作用是对多时给集合类型赋值,
                注意这里类型的标识为ofType-->
        <collection property="orderList" ofType="order">
            <id column="order_id" property="orderId"/>
            <result column="order_name" property="orderName"/>
            <result column="customer_id" property="customerId"/>
<!--            这里切记不要给order里的customer赋值-->
        </collection>
    </resultMap>
    <select id="queryCustomerById" resultMap="customerMap">
        select *
        from t_customer tur
                 join t_order tor
                      on tor.customer_id = tur.customer_id
        where tur.customer_id = #{id};
    </select>

7.编写测试代码并执行

执行结果:

多表映射的注意点(推荐点)

  • 对一关系只需要实体类在属性上包含对方对象
  • 对多关系只需要实体类在属性上包含对方对象列表
  • 只有发生多表联查时,才需要设计和修改实体类,否则不提前和修改设计实体类。
  • 无论多少张表联查,实体类设计都是两两考虑。即考虑两个表之间是一对一还是一对多关系。
  • 在查询映射是,只需要考虑本次查询相关的属性。如:上述两个类中,当查询订单数据时只考虑订单中的Customer属性,不再去深入查找Customer中的orderlist属性,不要形成死循环。

MyBatis动态语句

if 和 where 标签

接口方法:

Employee query(@Param("name") String name,@Param("salary") Double salary);

之前的sql语句

<select id="query" resultType="employee">
    select * from t_emp where emp_id = #{name} and emp_salary=#{salary};
</select>

但为防止name为null或salary为null,MyBatis提供了<if>:

<!--    test 内部可以直接使用接口方法的参数名
        test 内部做运算,为true则做拼接,为false则不拼接-->
    <select id="query" resultType="employee">
        select * from t_emp where
            <if test="name != null">
                emp_name = #{name}
            </if>
            <if test="">
                and emp_salary=#{salary}
            </if>
    </select>

但上式如果第一个if为false,第二个为true,sql就会变为:

select * from t_emp where and emp_salary=#{salary};

为防止此情况,MyBatis提供了<where>:

<!--    where标签作用:1.自动添加where关键字,当where标签内部有一个if满足,自动添加where关键字,否则不添加
                     2.自动去掉多余的and和or-->
    <select id="query" resultType="employee">
        select * from t_emp
            <where>
                <if test="name != null">
                    emp_name = #{name}
                </if>
                <if test="">
                    and emp_salary=#{salary}
                </if>
            </where>
    </select>

set标签

接口方法:

int update(Employee employee);

要求只有当employee中的name和salary不为null才执行语句

<!--    当第一个成立,第二个不成立时,sql多一个逗号-->
<update id="update">
    update t_emp set
    <if test="empName != null">
        emp_name = #{empName},
    </if>
    <if test="empSalary != null">
        emp_salary = #{empSalary}
    </if>
    where emp_id = #{empId};
</update>

<set>:1.自动去除多余的逗号  2.自动添加set关键字

<update id="update">
    update t_emp
        <set>
            <if test="empName != null">
                emp_name = #{empName},
            </if>
            <if test="empSalary != null">
                emp_salary = #{empSalary}
            </if>
        </set>
    where emp_id = #{empId};
</update>

trim标签(了解)

动态添加或去除前置词和后置词,可以替代where和set

choose/when/otherwise标签

在多个分支条件下,只选择一个。

判断顺序:从上往下判断,当有一个when为true就采纳,如果所有when都为false,执行otherwise

<select id="query1" resultType="employee">
    select * from t_emp
    where
        <choose>
            <when test="empName!=null">emp_name = #{name}</when>
            <when test="empSalary &gt; 100">and emp_salary=#{salary}</when>
            <otherwise>1=1</otherwise>
        </choose>
</select>

foreach标签(重点)

当需要批量操作时可以使用foreach,如:插入多个数据,根据id批量查询。

当参数传入一个List集合类型时,需要使用@Param("值")来设置它的名称,不然在collection属性中默认使用collection,list或arg0来引用这个List集合。

接口方法:

List<Employee> queryBatch(@Param("ids")List<Integer> idList);

int updateBatch(@Param("emps")List<Employee> empList);

xml文件sql:

<select id="queryBatch" resultType="employee">
    select * from t_emp
        where emp_id in
        <!--
            collection:要遍历的变量名,即传入的list参数名
            open:遍历前添加的字符串
            separator:每次遍历的分隔符,如果是最后一次遍历不会添加
            close:遍历后添加的字符串
            item:获取每个遍历项
            在foreach标签中可以使用#{item} 获取list中的每个元素
        -->
        <foreach collection="ids" open="(" separator="," close=")" item="id">
            #{id}
        </foreach>
</select>
<insert id="insertBatch">
    insert into t_emp (emp_name, emp_salary)
    values
        <foreach collection="emps" open="" close="" separator="," item="emp">
            (#{emp.empName},#{emp.empSalary})
        </foreach>
</insert>

当使用foreach操作update语句时,直接将整个sql语句包裹进去,此时将执行多次update语句,但需要设置MyBatis配置文件中连接数据库时的url,在url后面添加"?allowMultiQueries=true"(允许多语句执行)。

sql片段

抽取重复的sql片段:

<sql id="selectSQL">
    select * from t_emp
</sql>
<select id="queryBatch" resultType="employee">
    <include refid="selectSQL"/>
    where emp_id in
    <foreach collection="ids" open="(" separator="," close=")" item="id">
        #{id}
    </foreach>
</select>

MyBatis高级拓展

Mapper批量映射优化

如果有多个Mapper添加到MyBatis配置文件中mappers会十分繁琐,可以使用<package name=""

但要求MapperXML文件与mapper接口的命名必须相同并且最后打包后的位置要一致,都是在name指定的包下,有两种方法:

方法1:xml也放到mapper接口的包下(假设为src/main/java/com/qiu/mapper),但需要设置pom文件,不然项目编译打包时不会将java包下的xml文件打包。

    <build>
        <resources>
<!--            将src/main/java下的所有文件都打包-->
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
            </resource>
        </resources>
    </build>

方法2:在resources文件夹创建与src/main/java下相同的文件夹结构com/qiu/mapper,这样打包时会把两个文件夹内容打包到一起。

插件和分页插件PageHelper

MyBatis对插件进行了标准化设计,并提供了一套可拓展的插件机制。插件可以在用于语句执行过程中进行拦截,并允许通过自定义处理程序来拦截和修改sql语句、映射语句结果等。

PageHelper插件

对select查询到的数据进行limit处理,即获取数据集里的一段数据。该插件会在sql正式执行前在后面拼接上limit x,y ,所以写sql时结尾不要加 ; 。

PageHelper插件使用:

1、导依赖

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.11</version>
</dependency>

2、在MyBatis配置文件里配置分页插件

<!--        com.github.pagehelper.PageInterceptor为分页插件的名称-->
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--            插件语法对应的数据库类型-->
            <property name="helperDialect" value="mysql"/>
        </plugin>

逆向工程和MybatisX插件

orm思维持久层框架

java是面向对象的编程思维,数据库是面向过程的编程思维。

而orm思维指的是使用面向对象思维进行数据库操作。

MyBatis框架提供了一些crud方法,由框架转换为对数据库的操作,但sql需要自己编写,所以MyBatis框架是半自动orm思维持久层框架

全自动orm思维持久层框架如hibernate,只需要把数据库数据和java实体类映射(配置),它就能提供crud方法,而且会自动生成对应的sql语句。

将半自动orm框架 ->全自动orm框架就叫做逆向工程(MyBatis->mybatis-plus)

逆向工程插件MybatisX插件

1.安装MyBatisX插件

2.idea连接数据库

3.选择数据库的表右键

4.进行以下操作:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值