【Mybatis-Plus】连表查询 逻辑删除 多租户

embedded/2024/12/23 18:03:45/

文章目录

    • 连表查询
    • 逻辑删除
    • 多租户

连表查询

引入 mybatis-plus-join-boot-starter 依赖

<dependency><groupId>com.github.yulichang</groupId><artifactId>mybatis-plus-join-boot-starter</artifactId><version>1.5.1</version>
</dependency>

继承 MPJBaseMapper

java">public interface RoleMapper extends MPJBaseMapper<Role> {}public interface UserMapper extends MPJBaseMapper<User> {public UserRole findUserRole();
}

观察源码,MPJBaseMapper 继承了 BaseMapper,并添加了连表查询的功能。

java">public interface MPJBaseMapper<T> extends BaseMapper<T>, JoinMapper<T> {}

定义一个 JavaBean 存储用户和角色信息的组合。包含用户 ID (id)、角色 ID (rid)、用户名 (userName) 和角色名 (roleName)。

java">@Data
public class UserRole {private Integer id;private Integer rid;private String userName;private String roleName;
}

分别通过 MPJLambdaWrapperMPJQueryWrapper 来构建查询,获取包含用户和角色信息的 UserRole 对象列表。

java">@SpringBootTest
class UserMapperTest {@Resourceprivate UserMapper userMapper;@Testpublic void mpj(){MPJLambdaWrapper<User> lambdaWrapper = JoinWrappers.lambda(User.class).select(User::getId,User::getUserName).selectAs(Role::getId,UserRole::getRid).select(Role::getRoleName).leftJoin(Role.class,Role::getId,User::getUserRole);List<UserRole> userRoleList = userMapper.selectJoinList(UserRole.class, lambdaWrapper);userMapper.findUserRole();}
}
java">MPJQueryWrapper<User> queryWrapper = new MPJQueryWrapper<>();
queryWrapper.select("t.id,userName,t1.id as rid,roleName");
queryWrapper.leftJoin("smbms_role t1 on t.userRole = t1.id");
List<UserRole> userRoleList = userMapper.selectJoinList(UserRole.class, queryWrapper);
userMapper.findUserRole();

以上两种方式较少使用,最常用的还是使用 XML 文件来编写 SQL 语句

这种方式可以提供更细粒度的控制,并且使得 SQL 语句更加集中和清晰。

<mapper namespace="com.hz.mapper.UserMapper"><select id="findUserRole" resultType="com.hz.pojo.dto.userRole">SELECT t.id,userName,t1.id as rid,roleNameFROM smbms_user t LEFT JOIN smbms_role t1 on t.userRole = t1.id</select>
</mapper>
java">@SpringBootTest
class UserMapperTest {@Resourceprivate UserMapper userMapper;@Testpublic void mpj(){userMapper.findUserRole();}
}

逻辑删除

逻辑删除是一种优雅的数据管理策略,它通过在数据库中标记记录为“已删除”而非物理删除,来保留数据的历史痕迹,同时确保查询结果的整洁性。MyBatis-Plus 提供了便捷的逻辑删除支持,使得这一策略的实施变得简单高效。

MyBatis-Plus 的逻辑删除功能会在执行数据库操作时自动处理逻辑删除字段。以下是它的工作方式:

  • 插入:逻辑删除字段的值不受限制。
  • 查找:自动添加条件,过滤掉标记为已删除的记录。
  • 更新:防止更新已删除的记录。
  • 删除:将删除操作转换为更新操作,标记记录为已删除。

例如:

  • 删除update user set deleted=1 where id = 1 and deleted=0
  • 查找select id,name,deleted from user where deleted=0

使用步骤

1、配置全局属性

application.yml 中配置 MyBatis-Plus 的全局逻辑删除属性。

mybatis-plus:global-config:db-config:logic-delete-field: isdeleted # 全局逻辑删除字段名logic-delete-value: 1 # 逻辑已删除值logic-not-delete-value: 0 # 逻辑未删除值

2、使用 @TableLogic 注解

在这里插入图片描述

确保数据库表中已添加了逻辑删除字段,并设置默认值为逻辑未删除值。在实体类中,对应数据库表的逻辑删除字段上添加 @TableLogic 注解。

java">import com.baomidou.mybatisplus.annotation.TableLogic;
public class User {@TableLogicprivate Integer isdeleted;
}

3、测试

java">@SpringBootTest
public class ProviderServiceImplTest {@Resourceprivate ProviderService providerService;@Testpublic void find() {QueryWrapper<Provider> queryWrapper = new QueryWrapper<>();queryWrapper.select("id", "proCode", "proDesc", "proName");providerService.list(queryWrapper);}
}
java">JDBC Connection [HikariProxyConnection@23218037 wrapping com.mysql.cj.jdbc.ConnectionImpl@1e7f19b4] will not be managed by Spring
==>  Preparing: SELECT id,proCode,proDesc,proName FROM smbms_provider WHERE isdeleted=0
==> Parameters: 
<==    Columns: id, proCode, proDesc, proName
<==    ...

再测试一下删除

java">@Test
public void delete() {providerService.removeById(17);
}
java">==>  Preparing: UPDATE smbms_provider SET isdeleted=1 WHERE id=? AND isdeleted=0
==> Parameters: 17(Integer)
<==    Updates: 1

公共实体类(Common Entity Class)将多个实体类共有的属性和行为封装到一个单独的类中。

java">@Data
@TableName("smbms_provider")
public class Provider extends BaseEntity{// 数据库自增 ID 作为主键@TableId(value = "id", type = IdType.AUTO)private Integer id;   //idprivate String proCode; //供应商编码// 映射到数据库字段 proName as pname@TableField("proName")private String pname; //供应商名称private String proDesc; //供应商描述private String proContact; //供应商联系人private String proPhone; //供应商电话private String proAddress; //供应商地址private String proFax; //供应商传真
}
java">@Data
public class BaseEntity implements Serializable {private Integer createdBy; //创建者private String creationDate; //创建时间private Integer modifyBy; //更新者private String modifyDate;//更新时间@TableLogicprivate Integer isdeleted;
}

多租户

MyBatis-Plus 提供了 TenantLineInnerInterceptor 插件用于实现多租户的数据隔离。通过这个插件,可以确保每个租户只能访问自己的数据,从而实现数据的安全隔离。

关键属性

属性名类型默认值描述
tenantLineHandlerTenantLineHandler租户处理器( TenantId 行级 )

TenantLineHandler 接口定义了以下方法:

public interface TenantLineHandler {/*** 获取租户 ID 值表达式,只支持单个 ID 值** @return 租户 ID 值表达式*/Expression getTenantId();/*** 获取租户字段名* 默认字段名叫: tenant_id** @return 租户字段名*/default String getTenantIdColumn() {return "tenant_id";}/*** 根据表名判断是否忽略拼接多租户条件* 默认都要进行解析并拼接多租户条件** @param tableName 表名* @return 是否忽略, true:表示忽略,false:需要解析并拼接多租户条件*/default boolean ignoreTable(String tableName) {return false;}/*** 忽略插入租户字段逻辑** @param columns        插入字段* @param tenantIdColumn 租户 ID 字段* @return*/default boolean ignoreInsert(List<Column> columns, String tenantIdColumn) {return columns.stream().map(Column::getColumnName).anyMatch(i -> i.equalsIgnoreCase(tenantIdColumn));}
}

使用一下,先定义一个实现类 CustomTenantHandle 继承 TenantLineHandler 接口

java">@Component
public class CustomTenantHandler implements TenantLineHandler {@Overridepublic Expression getTenantId() {int userId = 2;return new LongValue(userId);}@Overridepublic String getTenantIdColumn() {return "createdBy";}@Overridepublic boolean ignoreTable(String tableName) {return false; // 拼接}
}

多租户数据库中,不同租户的数据存储在同一张表中,通过租户ID来区分。分页查询结合租户过滤条件可以确保每个租户只能访问到自己的数据。另外,分页也可以限制查询结果的数量,从而提高查询效率。

java">@Configuration
public class MybatisPlusConfig {@Resourceprivate CustomTenantHandler customTenantHandler;@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 多租户TenantLineInnerInterceptor tenantInterceptor = new TenantLineInnerInterceptor();tenantInterceptor.setTenantLineHandler(customTenantHandler);interceptor.addInnerInterceptor(tenantInterceptor);interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}
}

测试一下

java">@Test
public void findpage() {Page<Provider> page = new Page<>(1,5);providerService.page(page,null);
}

查询到 4 条记录

java">JDBC Connection [HikariProxyConnection@227080339 wrapping com.mysql.cj.jdbc.ConnectionImpl@259b85d6] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM smbms_provider WHERE isdeleted = 0 AND smbms_provider.createdBy = 2
==> Parameters: 
<==    Columns: total
<==        Row: 4
<==      Total: 1
==>  Preparing: SELECT id, proCode, proName AS pname, proDesc, proContact, proPhone, proAddress, proFax, createdBy, creationDate, modifyBy, modifyDate, isdeleted FROM smbms_provider WHERE isdeleted = 0 AND smbms_provider.createdBy = 2 LIMIT ?
==> Parameters: 5(Long)
<== ...

http://www.ppmy.cn/embedded/148130.html

相关文章

Deepin/Linux clash TUN模式不起作用,因网关导致的问题的解决方案。

网关导致的问题的解决方案 查看路由 ip route寻找默认路由 默认路由应当为Mihomo default dev Mihomo scope link 如果不是&#xff0c;则 sudo ip route add default dev Mihomo在clash TUN开关状态发生变化时&#xff0c;Mihomo网卡会消失&#xff0c;所以提示找不到网卡…

【活动邀请·深圳】深圳COC社区 深圳 AWS UG 2024 re:Invent re:Cap

re:Invent 是全球云计算领域的顶级盛会&#xff0c;每年都会吸引来自世界各地的技术领袖、创新者和实践者汇聚一堂&#xff0c;分享最新的技术成果和创新实践&#xff0c;深圳 UG 作为亚马逊云科技技术社区的重要组成部分&#xff0c;将借助 re:Invent 的东风&#xff0c;举办此…

C# Redis分布式锁

使用包StackExchange.Redis&#xff0c;可以在NuGet中下载到 可以支持多并发请求&#xff0c;保持数据一致性和不重复已经保证代码只再一次请求结束后再执行 public static async Task<bool> TryAcquireLockAsync() {bool isAcquired false;while (!isAcquired){isAcq…

fastAPI接口的请求与响应——基础

1. 后端接口 1.接口实现 pip install fastapi pip install uvicorn# api.py from pydantic import BaseModel from fastapi import FastAPI import uvicorn import os# 定义请求体模型 class Payload(BaseModel):key1: strkey2: str# 创建一个FastAPI应用程序实例 app Fast…

【数据结构】平衡二叉树

目录 一、概念 二、平衡二叉树的插入 &#xff08;一&#xff09;插入步骤 &#xff08;二&#xff09;旋转 1、左旋 2、右旋 3、左右双旋 4、右左双旋 三、特点 四、整体代码 一、概念 平衡二叉树是在二叉搜索树的改进&#xff0c;二叉搜索树详见&#xff1a;【数据结…

Linux系统加固

Linux系统安全加固 文章目录 Linux系统安全加固密码策略文件、目录安全未授权suid、未授权sgid排查与加固禁止root登录ftp、禁止匿名访问ftp计划任务排查与加固、开机自启排查与加固限定root用户远程ssh登录日志加固 无用账号、用户组和空口令账户排查与加固 禁用或删除无用账号…

【mysql】1205 -Lock wait timeout exceeded; try restarting transaction

问题&#xff1a; mysql8执行SQL提示下面错误&#xff1a; 1205 -Lock wait timeout exceeded; try restarting transaction 1205-超过锁定等待超时&#xff1b;尝试重新启动事务 可能的原因&#xff1a; 事务冲突&#xff1a;多个事务同时尝试修改同一行数据&#xff0c;导…

使用ElasticSearch实现全文检索

文章目录 全文检索任务描述技术难点任务目标实现过程1. java读取Json文件&#xff0c;并导入MySQL数据库中2. 利用Logstah完成MySQL到ES的数据同步3. 开始编写功能接口3.1 全文检索接口3.2 查询详情 4. 前端调用 全文检索 任务描述 在获取到数据之后如何在ES中进行数据建模&a…