Mybatis 框架使用指南(进阶)2

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: Mybatis 框架使用指南(进阶)2

嵌套查询(了解)


Mybatis嵌套查询 介绍:将多表查询的复杂sql语句拆分多个单表查询,再由mybatis框架进行嵌套组合


  • 优点:减少sql复杂性
  • 缺点:需要编写多次sql和多个配置,代码麻烦。故一般不推荐使用

简单示例:

* 需求:查询一个订单,与此同时查询出该订单所属的用户  1v1
# 关联查询
select * from orders o left join user u on o.uid=u.id where o.id=1;
# 嵌套查询 将一条sql语句能完成的事情拆分成多条单表查询去完成
#1 查询订单号为1的订单
#2 在根据查询的订单的uid去查用户表
#3 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="cn.test.mapper.OrdersMapper">
    <resultMap id="ordersResultMap" type="orders">
        <id column="id" property="id"></id>
        <result column="ordertime" property="ordertime"></result>
        <result column="address" property="address"></result>
        <!--mybatis框架嵌套查询(一对一映射)
                association标签
                    property:要封装的对象属性名
                    select:数据来源的方法名
                    column:方法需要的参数(uid)
        -->
        <association property="user" select="cn.test.mapper.UserMapper.findUserById" 
                     column="uid">
        </association>
    </resultMap>
    <!-- 查询当前订单 -->
    <select id="findOrderById" parameterType="int" resultMap="ordersResultMap">
        select * from orders where id=#{id}
    </select>
</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">
<mapper namespace="cn.test.mapper.UserMapper">
    <!-- 查询当前用户 -->
    <select id="findUserByUId" parameterType="int" resultType="user">
        select * from user where id=#{id}
    </select>
</mapper>



一对多

需求:查询一个用户,与此同时查询出该用户具有的订单

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="cn.test.mapper.UserMapper">
    <resultMap id="userResultMap" type="user">
        <id column="id" property="id"></id>
        <result column="username" property="username"></result>
        <result column="birthday" property="birthday"></result>
        <result column="sex" property="sex"></result>
        <result column="address" property="address"></result>
        <!-- 嵌套查询(一对多的映射)
                collection标签
                    property;要封装的对象集合属性
                    ofType:泛型类型
            select:数据的来源方法  
            column:方法需要的参数数据(用户的id) 
        -->
        <collection property="orders" ofType="Orders" select="cn.test.mapper.OrdersMapper.findBylist" 
                    column="id">
        </collection>
    <!-- 查询当前用户 -->
    </resultMap>
    <select id="findUserById" parameterType="int" resultMap="userResultMap">
        select * from user where id=#{id}
    </select>
</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">
<mapper namespace="cn.test.mapper.OrdersMapper">
    <!--查询多个订单-->
    <select id="findBylist" parameterType="int" resultType="Orders">
        select * from orders where uid=#{id}
    </select>
</mapper>



多对多(由二个一对多组成)

需求:查询用户同时查询出该用户的所有角色

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="cn.test.mapper.UserMapper">
    <resultMap id="userResultMap" type="user">
        <id column="id" property="id"></id>
        <result column="username" property="username"></result>
        <result column="birthday" property="birthday"></result>
        <result column="sex" property="sex"></result>
        <result column="address" property="address"></result>
        <!-- 嵌套查询(一对多的映射)
                collection标签
                    property;要封装的对象集合属性
                    ofType:泛型类型
                    select:数据的来源方法  
           column:方法需要的参数数据(用户的id)
        -->
        <collection property="roleList" ofType="role" select="cn.test.mapper.RoleMapper.findRoles" 
                    column="id">
        </collection>
    </resultMap>
    <!--查询当前用户-->
    <select id="findUserById" parameterType="int" resultMap="userResultMap">
        select * from user where id=#{id}
    </select>
</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">
<mapper namespace="cn.test.mapper.RoleMapper">
    <resultMap id="RoleResultMap" type="role">
        <id column="id" property="id"></id>
        <result column="role_name" property="roleName"></result>
        <result column="role_desc" property="roleDesc"></result>
    </resultMap>
    <!--查询当前用户的角色-->
    <select id="findRoles" resultMap="RoleResultMap" parameterType="int">
        SELECT * FROM user_role ur INNER JOIN role r ON ur.rid=r.id WHERE ur.uid=#{id}
    </select>
</mapper>



调用存储过程

参考:MyBatis 调用存储过程(详解)


在mapper文件中可以使用statementType标记使用什么的对象操作SQL语句。


statementType:标记操作SQL的对象


取值说明:

   STATEMENT:直接操作sql,不进行预编译,获取数据。$—Statement

   PREPARED:预处理,参数,进行预编译,获取数据。#—PreparedStatement。默认

   CALLABLE:执行存储过程。CallableStatement


示例:

  1. 创建insert_user存储过程(MySql)
CREATE PROCEDURE insert_user(OUT u_id INTEGER,IN u_name VARCHAR(20),IN u_sex VARCHAR(20),IN u_age INTEGER)
BEGIN
INSERT INTO t_user (name,sex,age) VALUES (u_name,u_sex,u_age);
SET u_id=LAST_INSERT_ID();
END


在UserMapper.xml中调用insert_user存储过程

<!-- 添加用户 -->
<insert id="addUser" parameterType="com.po.User" statementType="CALLABLE">
    {call insert_user(#{id,mode=OUT,jdbcType=INTEGER},#{name,mode=IN},#{sex,mode=IN},#{age,mode=IN})}
</insert>


2.创建deleteUser存储过程(MySql)

CREATE PROCEDURE deleteUser(IN u_id INTEGER)
BEGIN
   DELETE FROM t_user WHERE id=u_id;
END

在UserMapper.xml中调用deleteUser存储过程

<!-- 删除用户 -->
<delete id="deleteUser" parameterType="Integer" statementType="CALLABLE">
    {call deleteUser(#{id,mode=IN})}
</delete>



3.创建updateUser存储过程(MySql)

CREATE PROCEDURE updateUser(IN u_id INTEGER,IN u_name VARCHAR(20),IN u_sex VARCHAR(20),IN u_age INTEGER)
BEGIN
    UPDATE t_user SET name=u_name,sex=u_sex,age=u_age WHERE id=u_id;
END


在UserMapper.xml中调用updateUser存储过程

<!-- 更新用户 -->
<update id="updateUser" parameterType="user" statementType="CALLABLE">
    {call updateUser(#{id,mode=IN},#{name,mode=IN},#{sex,mode=IN},#{age,mode=IN})}
</update>


4.创建getUserById存储过程(MySql)

CREATE PROCEDURE getUserById(IN u_id INTEGER)
BEGIN
    SELECT id,name,sex,age FROM t_user WHERE id=u_id;
END


在UserMapper.xml中调用getUserById存储过程

<!-- 根据id查询用户 -->
<select id="getUserById" parameterType="Integer" resultType="user" statementType="CALLABLE">
    {call getUserById(#{id,mode=IN})}
</select>




拓展了解

Mybatis 核心文件概述



1)environments标签

数据库环境配置



 1.  其中,事务管理器(transactionManager)类型有两种:


   JDBC:

   这个配置就是直接使用了JDBC 的提交和回滚设置,由mybatis自己手动控制事务


   MANAGED:

   这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期。

   例如:mybatis与spring整合后,事务交给spring容器管理。


2.    其中,数据源(dataSource)常用类型有二种:


   UNPOOLED:

   这个数据源的实现只是每次被请求时打开和关闭连接。


   POOLED:

   这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来。使用的是mybatis自带的


2)properties标签

第三方属性配置

实际开发中,习惯将数据源的配置信息单独抽取成一个properties文件

   <properties resource="jdbc.properties"></properties> 
   <environments default="mysql">
        <!--mysql数据库环境-->
        <environment id="mysql">
            <!-- 使用JDBC类型事务管理器 -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 数据源(连接池)配置  POOLED-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>



3)typeAliases标签

实体类型别名配置

  <typeAliases>
        <!--指定一个实体类和对应的别名-->
        <!--<typeAlias type="com.test.domain.User" alias="user"></typeAlias>-->
        <!--指定当前包下所有的实体设置别名  默认: 别名(类名) -->
        <package name="com.test.domain"></package>
    </typeAliases>

394b79c9b16a400da863592cbe7fcec9.png


4)mappers标签

映射关系配置(加载映射配置文件)

<!-- 加载指定的src目录下的映射文件 -->
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>



核心配置文件标签顺序




Mybatis 的 API 概述


1)Resources

专门用于加载mybatis核心配置文件,返回的 io流

InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");



2)SqlSessionFactoryBuilder

专门用于生产SqlSessionFactory工厂对象

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);



3)SqlSessionFactory

一个项目只有一个工厂对象,生产sqlSession对象

// 需要手动提交事务,DML语句才会持久化到数据库中
SqlSession openSession(); // 【推荐】
// 设置是否开启自动提交,如果设置为true,开启自动提交事务
SqlSession openSession(boolean autoCommit);
  参数说明
    true:每一条DML类型语句都会自动提交事务
    false(默认值):需要手动提交事务



4)SqlSession

是mybatis核心对象,可以对数据库进行CRUD基本操作

//  方法
<T> T selectOne(String statement, Object parameter);
<E> List<E> selectList(String statement, Object parameter);
int insert(String statement, Object parameter);
int update(String statement, Object parameter);
int delete(String statement, Object parameter);
// 事务
void commit();
void rollback();




MyBatis 延迟加载(懒加载)


Mybatis的延迟加载是针对嵌套查询而言的,是指在进行查询的时候先只查询最外层的SQL,对于内层SQL将在需要使用的时候才查询出来。


使用延迟加载的场景:一对多、多对多

不推荐使用延迟加载的场景:一对一(使用 立即加载)

特别注意:延迟加载是基于 嵌套查询 组合使用

1)局部延迟加载

* 需要手动在每一个select相关标签中单独配置
  <association>、<collection>
    fetchType="lazy"  懒加载
    fetchType="eager" 立即加载


2)全局延迟加载

lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载,特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。默认值为false。

  <!-- 在核心配置文件SqlMapConfig.xml,设置全局参数 -->
    <settings>
        <!--开启懒加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
    </settings>


若是pringboot集成,在yaml配置文件中配置开启延迟加载。

mybatis:
  configuration:
    lazy-loading-enabled: true    #开启延时加载开关


注意:如果全局配置了延迟加载,那么一对一也会起作用

可以为一对一设置局部的立即加载,因为局部优先级高于全局延迟加载

<association property="user" javaType="User" column="uid" select="com.itheima.mapper.UserMapper.findById" 
             fetchType="eager"> 
</association>


3)指定触发延迟加载的方法配置

lazyLoadTriggerMethods 默认情况下仅仅支持自动将 equals,clone,hashCode,toString 这几个方法定义为延迟加载的加载触发方法。

* 在SqlMapConfig.xml核心配置文件,设置全局参数
  <settings>
    <!-- 如果将 Person 的 doLazyLoadingNow()方法加入这个列表中,
       则调用 doLazyLoadingNow()方法将会导致 Person 上的所有延迟加载属性的关联对象被执行加载。 -->
    <setting name="lazyLoadTriggerMethods" value="doLazyLoadingNow,equals,clone,hashCode,toString"/>
  </settings>


若是springboot集成,在yaml配置文件中配置

mybatis:
  configuration:
    lazy-loading-enabled: true    # 开启延时加载开关
    aggressive-lazy-loading: false  # 将积极加载改为消极加载(即按需加载),默认值就是false
    # 指定触发延迟加载的方法
    lazy-load-trigger-methods: "doLazyLoadingNow,equals,clone,hashCode,toString"
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2天前
|
SQL Java 数据库连接
持久层框架MyBatisPlus
持久层框架MyBatisPlus
持久层框架MyBatisPlus
|
16天前
|
缓存 Cloud Native 安全
探索阿里巴巴新型ORM框架:超越MybatisPlus?
【10月更文挑战第9天】在Java开发领域,Mybatis及其增强工具MybatisPlus长期占据着ORM(对象关系映射)技术的主导地位。然而,随着技术的发展,阿里巴巴集团推出了一种新型ORM框架,旨在提供更高效、更简洁的开发体验。本文将对这一新型ORM框架进行探索,分析其特性,并与MybatisPlus进行比较。
22 0
|
3月前
|
Java 数据库连接 Spring
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
文章是关于Spring、SpringMVC、Mybatis三个后端框架的超详细入门教程,包括基础知识讲解、代码案例及SSM框架整合的实战应用,旨在帮助读者全面理解并掌握这些框架的使用。
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
|
3月前
|
Java 数据库连接 mybatis
mybatis框架图
文章介绍了MyBatis框架的起源、发展和其作为持久层框架的功能,提供了MyBatis的框架图以帮助理解其结构和组件。
mybatis框架图
|
3月前
|
Java 数据库连接 mybatis
后端框架的学习----mybatis框架(9、多对一处理和一对多处理)
这篇文章介绍了在MyBatis框架中如何处理多对一和一对多的关联查询,通过定义`<resultMap>`和使用`<association>`与`<collection>`元素来实现对象间的关联映射。
|
3月前
|
Java 数据库连接 测试技术
后端框架的学习----mybatis框架(8、lombok)
这篇文章介绍了如何在MyBatis框架中使用lombok库来简化Java实体类的编写,包括在IDEA中安装Lombok插件、在项目中导入lombok依赖以及在实体类上使用Lombok提供的注解。
|
3月前
|
SQL Java 数据库连接
【Java 第十三篇章】MyBatis 框架介绍
MyBatis 原名 iBATIS,2001 年由 Clinton Begin 创建,以其简易灵活著称。2010 年更名以重塑品牌形象。MyBatis 通过 SQL 映射文件将 SQL 语句与 Java 代码分离,支持编写原生 SQL 并与方法映射。具备对象关系映射功能,简化数据库记录处理。支持动态 SQL 构建,灵活应对不同查询条件。内置缓存机制,提升查询效率。相比全功能 ORM,MyBatis 提供更高 SQL 控制度和更好的维护性,并易于与 Spring 等框架集成,广泛应用于 Java 数据访问层。
34 0
|
3月前
|
druid Java 数据库连接
SpringBoot项目整合MybatisPlus持久层框架+Druid数据库连接池,以及实现增删改查功能
SpringBoot项目整合MybatisPlus和Druid数据库连接池,实现基本的增删改查功能。
310 0
|
3月前
|
SQL Java 数据库连接
后端框架的学习----mybatis框架(5、分页)
这篇文章介绍了如何在MyBatis框架中实现分页功能,包括使用SQL的`limit`语句进行分页和利用MyBatis的`RowBounds`对象进行分页的方法。
|
3月前
|
SQL Java 数据库连接
后端框架的学习----mybatis框架(7、使用注解开发)
这篇文章讲述了如何使用MyBatis框架的注解方式进行开发,包括在接口上使用注解定义SQL语句,并通过动态代理实现对数据库的增删改查操作,同时强调了接口需要在核心配置文件中注册绑定。