基于MybatisPlus的多表查询

2020年12月6日 4点热度 0条评论 来源: 不_yu

基于MybatisPlus的多表查询

mybaitsPlus配置文档

mybatis3.x文档

目录:

一对一查询

      方式一:非select配置方式
      方式二,通过select进行多表查询

一对多查询(用户对应多账户示例)

      方式一:非select配置方式
      方式二,通过select进行多表查询

多对多查询(用户通过中间表对应多个角色示例)

      方式一:非select配置方式
      方式二,通过select进行多表查询

懒加载配置(基于MybatisPlus)

      配置懒加载的配置说明
      懒加载演示一对多关系的查询

MySQL函数使用

      自定义函数示例
      定义变量实现函数
      执行自己创建的函数
      Mybatis中执行函数
      业务中常用的函数

补充

      Mybatis的in查询,使用xml映射的标签

一对一查询

  • 返回目录

  • 这里我们可以简单的看一下我们的数据表

SELECT u.`id`,u.`user_name`,a.`uid`,a.`account_name` FROM USER u,account a
	WHERE u.id=a.uid;

SELECT u.id,u.`user_name`,ur.`uid`,ur.`rid`,r.`id`,r.`role_name` FROM USER u,user_role ur,role r
	WHERE u.id=ur.uid 
	AND ur.rid=r.id
	ORDER BY u.`id`;

1. 方式一:非select配置方式

1.1 说明(关键参数和优缺点)

  • 这里我们说的主表表示resultMap下面对应的第一个映射对象
resultMap参数 作用
id 标识符(用于标识和指定resultMap)
type 返回值类型(通常是JavaBean)
association参数 作用
property 当前类对应的多表字段的属性名
column 指定当前主表需要传递的表字段参数名称
javaType 指定的返回值类型(通常是JavaBean)
select 指定关联的select标签下的方法路径

优点:减少select标签的使用,可以直接在一个配置文件中完成多表操作
缺点:不是很灵活,无法实现懒加载

1.2 演示示例

// 结果
<!-- Account(id=null, uid=1, accountName=建设银行, money=null, user=User(status=null, role=null, id=null, userName=Daming, age=null, email=null, createTime=null, updateTime=null, version=null, deleted=null, password=null, uRole=null, roleList=null)) -->
// 映射关系在一个表中配置完毕
<resultMap id="accountUser" type="Account">
    <result column="uid" property="uid"></result>
    <result column="account_name" property="accountName"></result>
    <association property="user" javaType="User">
        <result column="user_name" property="userName"></result>
    </association>
</resultMap>

<select id="findUserByAccountUid" parameterType="int" resultMap="accountUser">
    select u.user_name,a.uid,a.account_name from account a,user u where a.id = #{ id} and a.uid=u.id;
</select>

2. 方式二,通过select进行多表查询

1.1 说明(关键参数和优缺点)

  • 这里我们说的主表表示resultMap下面对应的第一个映射对象
resultMap参数 作用
id 标识符(用于标识和指定resultMap)
type 返回值类型(通常是JavaBean)
association参数 作用
property 当前类对应的多表字段的属性名
column 指定当前主表需要传递的表字段参数名称
javaType 指定的返回值类型(通常是JavaBean)
select 指定关联的select标签下的方法路径

优点:灵活,可以实现懒加载
缺点:可能配置会比较麻烦,需要多个select标签

1.2 演示示例

// 结果
<!-- Account(id=null, uid=1, accountName=建设银行, money=null, user=User(status=null, role=null, id=null, userName=Daming, age=null, email=null, createTime=null, updateTime=null, version=null, deleted=null, password=null, uRole=null, roleList=null)) -->
// AccountMapper.xml下的配置
<resultMap id="accountUser" type="Account">
    <association property="user" column="uid" select="com.example.demo.mapper.UserMapper.findUserById"
                 javaType="User">

    </association>
</resultMap>

// UserMapper.xml下的配置
<!-- 一对一 -->
<select id="findUserById" parameterType="int" resultType="User">
    select user_name from user where id = #{ uid};
</select>

一对多查询(用户对应多账户示例)

1. 方式一:非select配置方式

1.1 说明(关键参数和优缺点)

  • 这里我们说的主表表示resultMap下面对应的第一个映射对象
resultMap参数 作用
id 标识符(用于标识和指定resultMap)
type 返回值类型(通常是JavaBean)
collection参数 作用
property 当前类对应的多表字段的属性名
column 指定当前主表需要传递的表字段参数名称
javaType 指定的返回值类型(常常使用ArrayList,并且这个参数可以省略,因为mybatis会帮助我们推断)
ofType 指定返回值的类型
select 指定关联的select标签下的方法路径

优点:减少select标签的使用,可以直接在一个配置文件中完成多表操作
缺点:不是很灵活,无法实现懒加载

1.2 演示示例

// 结果
<!-- User(status=null, role=null, id=null, userName=Daming, age=null, email=null, createTime=null, updateTime=null, version=null, deleted=null, password=null, uRole=null, roleList=null, accounts=[Account(id=0, uid=1, accountName=招商银行, money=1000, user=null), Account(id=1, uid=1, accountName=建设银行, money=1000, user=null), Account(id=2, uid=1, accountName=北京银行, money=1000, user=null)]) -->
<resultMap id="userAccounts" type="User">
    <id column="id" property="id"></id>
    <result column="user_name" property="userName"></result>
    <collection property="accounts" ofType="Account">
        <result column="account_name" property="accountName"></result>
    </collection>
</resultMap>

<select id="findUserAccounts" resultMap="userAccounts">
    select u.id,u.user_name,a.account_name from user u,account a where u.id = #{ id} and u.id = a.uid;
</select>

2. 方式二,通过select进行多表查询

1.1 说明(关键参数和优缺点)

  • 这里我们说的主表表示resultMap下面对应的第一个映射对象
resultMap参数 作用
id 标识符(用于标识和指定resultMap)
type 返回值类型(通常是JavaBean)
association参数 作用
property 当前类对应的多表字段的属性名
column 指定当前主表需要传递的表字段参数名称
javaType 指定的返回值类型(常常使用ArrayList,并且这个参数可以省略,因为mybatis会帮助我们推断)
ofType 指定返回值的类型
select 指定关联的select标签下的方法路径

优点:灵活,可以实现懒加载
缺点:可能配置会比较麻烦,需要多个select标签

1.2 演示示例

// UserMapper.xml 配置
<resultMap id="userAccounts" type="User">
    <collection property="accounts" ofType="Account" javaType="ArrayList" column="id"
                select="com.example.demo.mapper.AccountMapper.findAccountsByUid">

    </collection>
</resultMap>

<select id="findUserAccounts" resultMap="userAccounts">
    select u.id ,u.user_name from user u where u.id = #{ id};
</select>

// AccountMapper.xml 配置
<select id="findUserByAccountUid" parameterType="int" resultMap="accountUser">
    select u.user_name,a.uid,a.account_name from account a,user u where a.id = #{ id} and a.uid=u.id;
</select>

多对多查询(用户通过中间表对应多个角色示例)

1. 方式一:非select配置方式

1.1 说明(关键参数和优缺点)

  • 这里我们说的主表表示resultMap下面对应的第一个映射对象
resultMap参数 作用
id 标识符(用于标识和指定resultMap)
type 返回值类型(通常是JavaBean)
collection参数 作用
property 当前类对应的多表字段的属性名
column 指定当前主表需要传递的表字段参数名称
javaType 指定的返回值类型(常常使用ArrayList,并且这个参数可以省略,因为mybatis会帮助我们推断)
ofType 指定返回值的类型
select 指定关联的select标签下的方法路径

优点:减少select标签的使用,可以直接在一个配置文件中完成多表操作
缺点:不是很灵活,无法实现懒加载

1.2 演示示例

// 结果
<!-- User(status=null, role=null, id=null, userName=Daming, age=null, email=null, createTime=null, updateTime=null, version=null, deleted=null, password=null, uRole=null, roleList=null, accounts=[Account(id=0, uid=1, accountName=招商银行, money=1000, user=null), Account(id=1, uid=1, accountName=建设银行, money=1000, user=null), Account(id=2, uid=1, accountName=北京银行, money=1000, user=null)]) -->
<resultMap id="userAccounts" type="User">
    <id column="id" property="id"></id>
    <result column="user_name" property="userName"></result>
    <collection property="accounts" ofType="Account">
        <result column="account_name" property="accountName"></result>
    </collection>
</resultMap>

<select id="findUserAccounts" resultMap="userAccounts">
    select u.id,u.user_name,a.account_name from user u,account a where u.id = #{ id} and u.id = a.uid;
</select>

2. 方式二,通过select进行多表查询

1.1 说明(关键参数和优缺点)

  • 这里我们说的主表表示resultMap下面对应的第一个映射对象
resultMap参数 作用
id 标识符(用于标识和指定resultMap)
type 返回值类型(通常是JavaBean)
association参数 作用
property 当前类对应的多表字段的属性名
column 指定当前主表需要传递的表字段参数名称
javaType 指定的返回值类型(常常使用ArrayList,并且这个参数可以省略,因为mybatis会帮助我们推断)
ofType 指定返回值的类型
select 指定关联的select标签下的方法路径

优点:灵活,可以实现懒加载
缺点:可能配置会比较麻烦,需要多个select标签

1.2 演示示例

// 结果
<!-- User(status=null, role=null, id=null, userName=Daming, age=null, email=null, createTime=null, updateTime=null, version=null, deleted=null, password=null, uRole=null, roleList=null, accounts=[Account(id=0, uid=1, accountName=招商银行, money=1000, user=null), Account(id=1, uid=1, accountName=建设银行, money=1000, user=null), Account(id=2, uid=1, accountName=北京银行, money=1000, user=null)]) -->
<resultMap id="userRoles" type="User">
    <id column="id" property="id"></id>
    <result column="user_name" property="userName"></result>
    <collection property="roles" ofType="Role">
        <result column="role_name" property="roleName"></result>
    </collection>
</resultMap>

<select id="findUserRoles" parameterType="int" resultMap="userRoles">
    select u.id,u.user_name,r.role_name from user u,user_role ur,role r where u.id = #{ id} and u.id = ur.uid and ur.rid=r.id;
</select>

懒加载配置(基于MybatisPlus)

1. 配置懒加载的配置说明

1.1 如果通过配置文件配置的话,有下面两个配置

下面这些配置会比较方便,是全局配置

# 这个配置会默认直接让所有可以进行懒加载的<select>映射执行懒加载
#mybatis-plus.configuration.aggressive-lazy-loading=true
# 开启这个会根据需求进行懒加载
#mybatis-plus.configuration.lazy-loading-enabled=true

我们一般开启第二个配置

# 开启这个会根据需求进行懒加载
#mybatis-plus.configuration.lazy-loading-enabled=true

1.2 可以在标签<association>``<collection>里面配置

优点是更加灵活,可以指定需要进行懒加载的标签。但是配置会更加麻烦和增加维护难度。

  • 通过指定,fetchType="true"表示开启了懒加载

2. 懒加载演示一对多关系的查询

  • 返回目录

  • 这里我们演示比较灵活的配置方式(fetchType=“lazy”)

// UserMapper.xml 的配置
<resultMap id="userRoles" type="User">
    <collection property="roles" ofType="Role" column="id" select="com.example.demo.mapper.RoleMapper.findRoleByRid" fetchType="lazy">

    </collection>
</resultMap>

<select id="findUserRoles" parameterType="int" resultMap="userRoles">
    select u.id,u.user_name from user u where u.id = #{ id};
</select>

// RoleMapper.xml 的配置
<select id="findRoleByRid" parameterType="int" resultType="Role">
    select r.role_name from user_role ur,role r where ur.uid = #{ id} and ur.rid=r.id;
</select>

2.1 情况一:如果我们仅仅需要一张表中的信息,那么我们懒加载就不会去查询第二张表中的信息

// 这里我们仅仅需要User表中的信息,但是其中的角色结果我们并不需要查询出来,于是我们可以看下面的日志
User userRoles = userMapper.findUserRoles(1);
String userName = userRoles.getUserName();
System.out.println(userName);

日志

// 我们可以看到这里仅仅对一张表进行了查询,就可以提升我们程序的运行性能
=>  Preparing: select u.id,u.user_name from user u where u.id = ?;
==> Parameters: 1(Integer)
<==    Columns: id, user_name
<==        Row: 1, Daming
<==      Total: 1
 Time:63 ms - ID:com.example.demo.mapper.UserMapper.findUserRoles
Execute SQL:
    select
        u.id,
        u.user_name
    from
        user u
    where
        u.id = 1;

Daming

2.2 情况二:当我们需要用到第二张表的数据的时候,懒加载就会将第二张表的数据查询出来**

// 这里我们需要User表和Role表中的信息,懒加载会执行所有语句,于是我们可以看下面的日志
User userRoles = userMapper.findUserRoles(1);
System.out.println(userRoles);
// 可以看到下面首先查了第一张表的数据,然后接着查询出来了第二张表的数据
=>  Preparing: select u.id,u.user_name from user u where u.id = ?;
==> Parameters: 1(Integer)
<==    Columns: id, user_name
<==        Row: 1, Daming
<==      Total: 1
 Time:63 ms - ID:com.example.demo.mapper.UserMapper.findUserRoles
Execute SQL:
    select
        u.id,
        u.user_name
    from
        user u
    where
        u.id = 1;

Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4288d98e]
JDBC Connection [HikariProxyConnection@860798122 wrapping com.mysql.jdbc.JDBC4Connection@6b6b3572] will not be managed by Spring
==>  Preparing: select r.role_name from user_role ur,role r where ur.uid = ? and ur.rid=r.id;
==> Parameters: 1(Integer)
<==    Columns: role_name
<==        Row: ROOT
<==        Row: ORDINARY
<==        Row: ADMIN
<==      Total: 3
 Time:1 ms - ID:com.example.demo.mapper.RoleMapper.findRoleByRid
Execute SQL:
    select
        r.role_name
    from
        user_role ur,
        role r
    where
        ur.uid = 1
        and ur.rid=r.id;

User(status=null, role=null, id=null, userName=Daming, age=null, email=null, createTime=null, updateTime=null, version=null, deleted=null, password=null, roles=[Role(id=null, roleName=ROOT, roleDesc=null), Role(id=null, roleName=ORDINARY, roleDesc=null), Role(id=null, roleName=ADMIN, roleDesc=null)], accounts=null)

MySQL函数使用

1. 自定义函数示例

返回目录

1.1 直接返回Sql语句结果

CREATE DEFINER=`root`@`%` FUNCTION `funName`(`N` VARCHAR(40)) RETURNS varchar(40) CHARSET utf8
BEGIN
RETURN (SELECT id FROM info_dormitory WHERE id=N);
END

2. 定义变量实现函数

返回目录

CREATE DEFINER=`root`@`%` FUNCTION `funName`(`N` VARCHAR(40),`No` VARCHAR(40)) RETURNS varchar(40) CHARSET utf8
BEGIN
DECLARE x VARCHAR(255) DEFAULT '';
SET x = (SELECT id FROM info_dormitory WHERE id = N AND dormitory_no = No);
RETURN x;
END

3. 执行自己创建的函数

返回目录

SELECT funName('1','3301');

4. Mybatis中执行函数

返回目录

<select id="funName" parameterType="java.lang.String" resultType="java.lang.String">
    SELECT funName(#{ name});
</select>

5. 业务中常用的函数

返回目录

1IF(expr,v1,v2)

如果expr是TRUE则返回v1,否则返回v2

(2IFNULL(v1,v2)

如果v1不为NULL,则返回v1,否则返回v2

补充

1. Mybatis的in查询,使用xml映射的标签

1.1 测试示例

@Test
public void test04() { 
    List<User> userByIdList = userMapper.findUserByIdList(Arrays.asList(1, 2, 3));
    userByIdList.stream().forEach(user -> System.out.println(user));
}

1.2 常用的使用方式,这里我们代入的参数是 ArrayList ,然后通过遍历进行逐个取值

<!-- 这里演示的是常用的Sql拼接逻辑 -->
<!--
    select
        u.id,
        u.user_name
    from
        user u
    where
        u.id in (
            1 , 2 , 3
        )
-->
<select id="findUserByIdList" parameterType="ArrayList" resultType="User">
    select u.id,u.user_name from user u where u.id in
    <foreach collection="list" index="i" item="item" open="(" separator="," close=")">
        #{ item}
    </foreach>
</select>

1.2 基本原理,也就是字符串的拼接,最后成为一个完整的sql语句,我们可以先写好sql语句,然后进行拼接

<!--
    select
        u.id,
        u.user_name
    from
        user u
    where
        u.id = 1
        and u.id = 2
        and u.id = 3 ;
-->
<!-- 其本质就是字符串的拼接,下面的拼接逻辑如:
        open + #{ item} + separator + #{ item} + close
 -->
<select id="findUserByIdList" parameterType="ArrayList" resultType="User">
    select u.id,u.user_name from user u where u.id =
    <foreach collection="list" index="i" item="item" open="" separator=" and u.id = " close=";">
        #{ item}
    </foreach>
</select>
    原文作者:不_yu
    原文地址: https://blog.csdn.net/qq_43230007/article/details/107119882
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。