C#入坑JAVA MyBatis入门 CURD 批量 联表分页查询

本文,分享 MyBatis 各种常用操作,不限于链表查询、分页查询等等。

1. 分页查询

在 下文的 的「3.4 selectPage」小节,我们使用 MyBatis Plus 实现了分页查询。除了这种方式,我们也可以使用 XML 实现分页查询。

这里,以查询 system_users 表为例,讲解如何使用 XML 实现分页查询。

#1.1 方案一:MyBatis XML

这个是 MyBatis 内置的使用方式,步骤如下:

分页案例 01

① 创建 AdminUserMapper.xml 文件,编写两个 SQL 查询语句:

<?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.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper"><select id="selectPage01List"resultType="cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO" >SELECT * FROM system_users<where><if test="reqVO.username != null and reqVO.username !=''">AND username LIKE CONCAT('%',#{reqVO.username},'%')</if><if test="reqVO.createTime != null">AND create_time BETWEEN #{reqVO.createTime[0]}, #{reqVO.createTime[1]},</if><if test="reqVO.status != null">AND status = #{reqVO.status}</if></where>ORDER BY id DESCLIMIT #{reqVO.pageNo}, #{reqVO.pageSize}</select><select id="selectPage01Count" resultType="Long" >SELECT COUNT(1) FROM system_users<where><if test="reqVO.username != null and reqVO.username !=''">AND username LIKE CONCAT('%',#{reqVO.username},'%')</if><if test="reqVO.createTime != null">AND create_time BETWEEN #{reqVO.createTime[0]}, #{reqVO.createTime[1]},</if><if test="reqVO.status != null">AND status = #{reqVO.status}</if></where></select></mapper>

② 在 AdminUserMapper 创建这两 SQL 对应的方法:

@Mapper
public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {/*** 查询分页的列表*/List<AdminUserDO> selectPage01List(@Param("reqVO") UserPageReqVO reqVO);/*** 查询分页的条数*/Long selectPage01Count(@Param("reqVO") UserPageReqVO reqVO);}

其中 UserPageReqVO.java (opens new window)是分页查询的请求 VO。

③ 在 AdminUserServiceImplService 层,调用这两个方法,实现分页查询:

@Service
@Slf4j
public class AdminUserServiceImpl implements AdminUserService {@Overridepublic PageResult<AdminUserDO> getUserPage(UserPageReqVO reqVO) {return new PageResult<>(userMapper.selectPage01List(reqVO),userMapper.selectPage01Count(reqVO));}
}

④ 简单调用下,可以在 IDEA 控制台看到 2 条 SQL:

分页案例 01 的效果

#1.2 方案二:MyBatis Plus XML

这个是 MyBatis Plus 拓展的使用方式,可以简化只需要写一条 SQL,步骤如下:

分页案例 02

① 创建 AdminUserMapper.xml 文件,只编写一个 SQL 查询语句:

<?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.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper"><select id="selectPage02"resultType="cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO" >SELECT * FROM system_users<where><if test="reqVO.username != null and reqVO.username !=''">AND username LIKE CONCAT('%',#{reqVO.username},'%')</if><if test="reqVO.createTime != null">AND create_time BETWEEN #{reqVO.createTime[0]}, #{reqVO.createTime[1]},</if><if test="reqVO.status != null">AND status = #{reqVO.status}</if></where>ORDER BY id DESC</select></mapper>

注意,不需要写 LIMIT 分页语句噢。

② 在 AdminUserMapper 创建这一 SQL 对应的方法:

@Mapper
public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {IPage<AdminUserDO> selectPage02(IPage<AdminUserDO> page, @Param("reqVO") UserPageReqVO reqVO);}

第一个参数、返回结果必须都是 IPage 类型,第二个参数可以放查询条件。

③ 在 AdminUserServiceImplService 层,调用这一个方法,实现分页查询:

@Service
@Slf4j
public class AdminUserServiceImpl implements AdminUserService {@Overridepublic PageResult<AdminUserDO> getUserPage(UserPageReqVO reqVO) {// 必须使用 MyBatis Plus 的分页对象IPage<AdminUserDO> page = new Page<>(reqVO.getPageNo(), reqVO.getPageSize());userMapper.selectPage02(page, reqVO);return new PageResult<>(page.getRecords(), page.getTotal());}
}

因为项目使用 PageParam 和 PageResult 作为分页对象,所以需要和 IPage 做下转换。

④ 简单调用下,可以在 IDEA 控制台看到 2 条 SQL:

分页案例 02 的效果

本质上,MyBatis Plus 是基于我们在 XML 编写的这条 SQL,计算出获得分页数量的 SQL。

一般情况下,建议采用方案二:MyBatis Plus XML,因为它开发效率更高,并且在分页数量为 0 时,就不多余查询分页的列表,一定程度上可以提升性能。

#2. 联表查询

对于需要链表查询的场景,建议也是写 MyBatis XML,使用方法比较简单,可以看下 《MyBatis学习总结(三)—— 多表关联查询与动态 SQL》 (opens new window)文章。

除了 XML 这种方式外,项目也集成了 MyBatis Plus Join (opens new window)框架,通过 Java 代码实现联表查询。

这里,以查询 system_users 和 system_dept 联表,查询部门名为  音娱乐行、用户状态为开启的用户列表。

#2.1 案例一:字段平铺

① 创建 AdminUserDetailDO 类,继承 AdminUserDO 类,并添加 deptName 平铺。代码如下:

@Data
public class AdminUserDetailDO extends AdminUserDO {private String deptName;}

② 在 AdminUserMapper 创建 selectListByStatusAndDeptName 方法,代码如下:

@Mapper
public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {default List<AdminUserDetailDO> selectList2ByStatusAndDeptName(Integer status, String deptName) {return selectJoinList(AdminUserDetailDO.class, new MPJLambdaWrapper<AdminUserDO>() // 查询 List.selectAll(AdminUserDO.class) // 查询 system_users 表的 all 所有字段.selectAs(DeptDO::getName, AdminUserDetailDO::getDeptName) // 查询 system_dept 表的 name 字段,使用 deptName 字段“部分”返回.eq(AdminUserDO::getStatus, status) // WHERE system_users.status = ? 【部门名为 `芋道源码`】.leftJoin(DeptDO.class, DeptDO::getId, AdminUserDO::getDeptId) // 联表 WHERE system_users.dept_id = system_dept.id .eq(DeptDO::getName, deptName) // WHERE system_dept.name = ? 【用户状态为开启】);}}

#2.2 案例二:字段内嵌

① 创建 AdminUserDetailDO 类,继承 AdminUserDO 类,并添加 dept 部门。代码如下:

@Data
public class AdminUserDetail2DO extends AdminUserDO {private DeptDO dept;}

② 在 AdminUserMapper 创建 selectListByStatusAndDeptName 方法,代码如下:

@Mapper
public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {default List<AdminUserDetail2DO> selectListByStatusAndDeptName(Integer status, String deptName) {return selectJoinList(AdminUserDetail2DO.class, new MPJLambdaWrapper<AdminUserDO>().selectAll(AdminUserDO.class).selectAssociation(DeptDO.class, AdminUserDetail2DO::getDept) // 重点差异点:查询 system_dept 表的 name 字段,使用 dept 字段“整个”返回.eq(AdminUserDO::getStatus, status).leftJoin(DeptDO.class, DeptDO::getId, AdminUserDO::getDeptId).eq(DeptDO::getName, deptName));}}

#2.3 总结

MyBatis Plus Join 相比 MyBatis XML 来说,一开始肯定是需要多看看它的文档 (opens new window)。

但是熟悉后,我还是更喜欢使用 MyBatis Plus Join 哈~

《MyBatis 数据库》MyBatis 是最容易读懂的 Java 框架之一

1. 实体类

BaseDO (opens new window) 是所有数据库实体的父类,代码如下:

@Data
public abstract class BaseDO implements Serializable {/*** 创建时间*/@TableField(fill = FieldFill.INSERT)private Date createTime;/*** 最后更新时间*/@TableField(fill = FieldFill.INSERT_UPDATE)private Date updateTime;/*** 创建者,目前使用 AdminUserDO / MemberUserDO 的 id 编号** 使用 String 类型的原因是,未来可能会存在非数值的情况,留好拓展性。*/@TableField(fill = FieldFill.INSERT)private String creator;/*** 更新者,目前使用 AdminUserDO / MemberUserDO 的 id 编号** 使用 String 类型的原因是,未来可能会存在非数值的情况,留好拓展性。*/@TableField(fill = FieldFill.INSERT_UPDATE)private String updater;/*** 是否删除*/@TableLogicprivate Boolean deleted;}
  • createTime + creator 字段,创建人相关信息。
  • updater + updateTime 字段,创建人相关信息。
  • deleted 字段,逻辑删除。

对应的 SQL 字段如下:

`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',

#1.1 主键编号

id 主键编号,推荐使用 Long 型自增,原因是:

  • 自增,保证数据库是按顺序写入,性能更加优秀。
  • Long 型,避免未来业务增长,超过 Int 范围。

对应的 SQL 字段如下:

`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

项目的 id 默认采用数据库自增的策略,如果希望使用 Snowflake 雪花算法,可以修改 application.yaml 配置文件,将配置项 mybatis-plus.global-config.db-config.id-type 修改为 ASSIGN_ID。如下图所示:

配置 Snowflake 雪花算法

#1.2 逻辑删除

所有表通过 deleted 字段来实现逻辑删除,值为 0 表示未删除,值为 1 表示已删除,可见 application.yaml 配置文件的 logic-delete-value 和 logic-not-delete-value 配置项。如下图所示:

逻辑删除的配置

① 所有 SELECT 查询,都会自动拼接 WHERE deleted = 0 查询条件,过滤已经删除的记录。如果被删除的记录,只能通过在 XML 或者 @SELECT 来手写 SQL 语句。例如说:

不自动过滤逻辑删除

② 建立唯一索引时,需要额外增加 delete_time 字段,添加到唯一索引字段中,避免唯一索引冲突。例如说,system_users 使用 username 作为唯一索引:

  • 未添加前:先逻辑删除了一条 username = yudao 的记录,然后又插入了一条 username = yudao 的记录时,会报索引冲突的异常。
  • 已添加后:先逻辑删除了一条 username = yudao 的记录并更新 delete_time 为当前时间,然后又插入一条 username = yudao 并且 delete_time 为 0 的记录,不会导致唯一索引冲突。

#1.3 自动填充

DefaultDBFieldHandler (opens new window) 基于 MyBatis 自动填充机制,实现 BaseDO 通用字段的自动设置。代码如下如:

DefaultDBFieldHandler 自动填充

#1.4 “复杂”字段类型

MyBatis Plus 提供 TypeHandler 字段类型处理器,用于 JavaType 与 JdbcType 之间的转换。示例如下:

字段处理器的示例

常用的字段类型处理器有:

  • JacksonTypeHandler (opens new window):通用的 Jackson 实现 JSON 字段类型处理器。
  • JsonLongSetTypeHandler (opens new window):针对 Set<Long> 的 Jackson 实现 JSON 字段类型处理器。

另外,如果你后续要拓展自定义的 TypeHandler 实现,可以添加到 cn.iocoder.yudao.framework.mybatis.core.type (opens new window)包下。

注意事项:

使用 TypeHandler 时,需要设置实体的 @TableName 注解的 @autoResultMap = true

#2. 编码规范

① 数据库实体类放在 dal.dataobject 包下,以 DO 结尾;数据库访问类放在 dal.mysql 包下,以 Mapper 结尾。如下图所示:

包规范


② 数据库实体类的注释要完整,特别是哪些字段是关联(外键)、枚举、冗余等等。例如说:

包规范


③ 禁止在 Controller、Service 中,直接进行 MyBatis Plus 操作。原因是:大量 MyBatis 操作散落在 Service 中,会导致 Service 的代码越来乱,无法聚焦业务逻辑。

示例
错误

正确

并且,通过只允许将 MyBatis Plus 操作编写 Mapper 层,更好的实现 SELECT 查询的复用,而不是 Service 会存在很多相同且重复的 SELECT 查询的逻辑。


④ Mapper 的 SELECT 查询方法的命名,采用 Spring Data 的 "Query methods" (opens new window)策略,方法名使用 selectBy查询条件 规则。例如说:

SELECT 命名示例


⑤ 优先使用 LambdaQueryWrapper 条件构造器,使用方法获得字段名,避免手写 "字段" 可能写错的情况。例如说:

LambdaQueryWrapper 条件构造器


⑥ 简单的单表查询,优先在 Mapper 中通过 default 方法实现。例如说:

单表查询

#3. CRUD 接口

BaseMapperX (opens new window)接口,继承 MyBatis Plus 的 BaseMapper 接口,提供更强的 CRUD 操作能力。

#3.1 selectOne

#selectOne(...) (opens new window)方法,使用指定条件,查询单条记录。示例如下:

selectOne 示例

#3.2 selectCount

#selectCount(...) (opens new window)方法,使用指定条件,查询记录的数量。示例如下:

selectCount 示例

#3.3 selectList

#selectList(...) (opens new window)方法,使用指定条件,查询多条记录。示例如下:

selectList 示例

#3.4 selectPage

针对 MyBatis Plus 分页查询的二次分装,在 BaseMapperX (opens new window)中实现,目的是使用项目自己的分页封装:

  • 【入参】查询前,将项目的分页参数 PageParam (opens new window),转换成 MyBatis Plus 的 IPage 对象。
  • 【出参】查询后,将 MyBatis Plus 的分页结果 IPage,转换成项目的分页结果 ​​​​​​​PageResult (opens new window)。代码如下图:

BaseMapperX 实现

具体的使用示例,可见 ​​​​​​​TenantMapper (opens new window)类中,定义 selectPage 查询方法。代码如下:

@Mapper
public interface TenantMapper extends BaseMapperX<TenantDO> {default PageResult<TenantDO> selectPage(TenantPageReqVO reqVO) {return selectPage(reqVO, new LambdaQueryWrapperX<TenantDO>().likeIfPresent(TenantDO::getName, reqVO.getName()) // 如果 name 不为空,则进行 like 查询.likeIfPresent(TenantDO::getContactName, reqVO.getContactName()).likeIfPresent(TenantDO::getContactMobile, reqVO.getContactMobile()).eqIfPresent(TenantDO::getStatus, reqVO.getStatus()) // 如果 status 不为空,则进行 = 查询.betweenIfPresent(TenantDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) // 如果 create 不为空,则进行 between 查询.orderByDesc(TenantDO::getId)); // 按照 id 倒序}}

完整实战,可见 《开发指南 —— 分页实现》 文档。

#3.5 insertBatch

#insertBatch(...) (opens new window)方法,遍历数组,逐条插入数据库中,适合少量数据插入,或者对性能要求不高的场景。 示例如下:

insertBatch 示例

为什么不使用 insertBatchSomeColumn 批量插入?

  • 只支持 MySQL 数据库。其它 Oracle 等数据库使用会报错,可见 InsertBatchSomeColumn (opens new window)说明。
  • 未支持多租户。插入数据库时,多租户字段不会进行自动赋值。

#4. 批量插入

绝大多数场景下,推荐使用 MyBatis Plus 提供的 IService 的 #saveBatch() (opens new window)​​​​​​​方法。示例 PermissionServiceImpl (opens new window)如下:

saveBatch 示例

#5. 条件构造器

继承 MyBatis Plus 的条件构造器,拓展了 LambdaQueryWrapperX (opens new window)和 QueryWrapperX (opens new window)类,主要是增加 xxxIfPresent 方法,用于判断值不存在的时候,不要拼接到条件中。例如说:

xxxIfPresent 方法

具体的使用示例如下:

LambdaQueryWrapperX 使用示例

#6. Mapper XML

默认配置下,MyBatis Mapper XML 需要写在各 yudao-module-xxx-biz 模块的 resources/mapper 目录下。示例 TestDemoMapper.xml (opens new window)如下:

TestDemoMapper.xml 示例

尽量避免数据库的连表(多表)查询,而是采用多次查询,Java 内存拼接的方式替代。例如说:

UserController 示例

#7. 字段加密

EncryptTypeHandler (opens new window),基于 Hutool AES (opens new window)实现字段的解密与解密。

例如说,数据源配置 (opens new window)的 password 密码需要实现加密存储,则只需要在该字段上添加 EncryptTypeHandler 处理器。示例代码如下:

@TableName(value = "infra_data_source_config", autoResultMap = true) // ① 添加 autoResultMap = true
public class DataSourceConfigDO extends BaseDO {// ... 省略其它字段/*** 密码*/@TableField(typeHandler = EncryptTypeHandler.class) // ② 添加 EncryptTypeHandler 处理器private String password;}

另外,在 application.yaml 配置文件中,可使用 mybatis-plus.encryptor.password 设置加密密钥。

字段加密后,只允许使用精准匹配,无法使用模糊匹配。示例代码如下:

@Test // 测试使用 password 查询,可以查询到数据
public void testSelectPassword() {// mock 数据DataSourceConfigDO dbDataSourceConfig = randomPojo(DataSourceConfigDO.class);dataSourceConfigMapper.insert(dbDataSourceConfig);// @Sql: 先插入出一条存在的数据// 调用DataSourceConfigDO result = dataSourceConfigMapper.selectOne(DataSourceConfigDO::getPassword,EncryptTypeHandler.encrypt(dbDataSourceConfig.getPassword())); // 重点:需要使用 EncryptTypeHandler 去加密查询字段!!!
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/458892.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1-petalinux2018.3 摸索记录 -petalinux-config

一、petalinux-config的具体配置-ZYNQMP Configuration 1、Linux Compoment Selection Linux Compoment Selection&#xff0c;Linux组件选择. First Stage Bootloader和Auto update ps_init勾选会自动生成fsbl.elf&#xff0c;自动更新ps_init。 PMU Firmware平台管理单元固…

熵与信息论

经典信息论的核心概念是香农熵。假设我们得到了一个变量X的值&#xff0c;X的香农熵量化了我们在获悉 X的值时所能得到的平均信息量&#xff1b;另一种观点是将X的看作在我们获悉的值前对其不确定程度的度量。这两种观点是互补的&#xff1b;我们既可以将看作在我们获悉X的值前…

Ubuntu 22.04系统启动时自动运行ROS2节点

在 Ubuntu 启动时自动运行 ROS2 节点的方法 环境&#xff1a;Ubuntu 系统&#xff0c;ROS2 Humble&#xff0c;使用系统自带的 启动应用程序 目标&#xff1a;在系统启动时自动运行指定的 ROS2 节点 效果展示 系统启动后&#xff0c;自动运行小乌龟节点和键盘控制节点。 实践…

龙蟠科技业绩压力显著:资产负债率持续攀升,产能利用率也不乐观

《港湾商业观察》施子夫 黄懿 去年十月至今两度递表后&#xff0c;10月17日&#xff0c;江苏龙蟠科技股份有限公司(以下简称&#xff0c;龙蟠科技&#xff1b;603906.SH&#xff0c;02465.HK)通过港交所主板上市聆讯。 很快&#xff0c;龙蟠科技发布公告称&#xff0c;公司全…

OceanBase 安全体系解析之身份鉴别

本文作者&#xff1a;金长龙爱可生测试工程师&#xff0c;负责 DMP 产品的测试工作。 本文以MySQL为参照&#xff0c;详细阐述了OceanBase 在MySQL模式下的安全体系中&#xff0c;身份鉴别的能力&#xff0c;涵盖了身份鉴别机制、用户名的构成规则、密码的复杂度&#xff0c;以…

在Java中的动态绑定和静态绑定

动态绑定和静态绑定是两种方法调用的绑定机制静态绑定 静态绑定也称为早期绑定&#xff0c;是在编译时确定调用的方法。动态绑定 动态绑定也称为晚期绑定&#xff0c;是在运行时确定调用的方法。静态绑定用于编译时确定的方法调用&#xff0c;动态绑定是Java实现运行时多态的…

CISE|暴雨受邀出席第二十六届中国国际软件博览会

10月24日至26日&#xff0c;备受瞩目的第二十六届中国国际软件博览会&#xff08;简称CISE&#xff09;在国家会展中心&#xff08;天津&#xff09;圆满举办。CISE不仅汇聚了来自全国各地的顶尖软件企业和机构&#xff0c;还吸引了众多专家学者和行业精英共襄盛举&#xff0c;…

Cesium基础-(Entity)-(Box)

** 里边包含Vue、React框架代码详细步骤、以及代码详细解释 ** 3、Box 盒子 以下是 BoxGeometry 类的属性、方法和静态方法,以表格形式展示: 属性 属性名类型默认值描述minimumCartesian3盒子的最小 x, y, 和 z 坐标。maximumCartesian3盒子的最大 x, y, 和 z 坐标。vertex…

【PHP】PHP使用Modbus-Rut协议与RS485串口通信,向设备发送和接收数据

目录 一、前言 二、开发前说明 三、效果图 四、安装PHP扩展 五、安装phpModbus类库 六、通信逻辑 七、完整实例 一、前言 使用PHP语言与硬件设备通信交互&#xff0c;并向COM串口发送和接收数据。 前面写了三篇关于PHP与RS235和USB端口通信的文章&#xff0c;可以作为参…

现代数字信号处理I--最佳线性无偏估计 BLUE 学习笔记

目录 1. 最佳线性无偏估计的由来 2. 简单线性模型下一维参数的BLUE 3. 一般线性模型下一维参数的BLUE 4. 一般线性模型下多维参数的BLUE 4.1 以一维情况说明Rao论文中的结论 4.2 矢量参数是MVUE的本质是矢量参数中的每个一维参数都是MVUE 4.3 一般线性模型多维参数BLUE的…

视频剪辑哪个软件好用?推荐四款热门工具!!

在这个Vlog和短视频当道的互联网时代&#xff0c;掌握一款好用的视频剪辑软件就像拥有了打开创作世界的魔法钥匙。今天我们来聊聊视频剪辑软件&#xff0c;帮你成为剪辑达人哦&#xff01;接下来&#xff0c;给大家详细介绍四款常用且各具特色的视频剪辑软件&#xff0c;助你轻…

算法:利用前序序列和中序序列构造二叉树

题目 链接&#xff1a;leetcode链接 思路分析 前序遍历的顺序是&#xff1a;根 左子树 右子树 中序遍历的顺序是&#xff1a; 左子树 根 右子树 所以&#xff0c;我们可以通过前序遍历获得二叉树的根 可以通过中序遍历去分割二叉树&#xff0c;将二叉树分割成 左子树 根…

偷懒总结篇|贪心算法|动态规划|单调栈|图论

由于这周来不及了&#xff0c;先过一遍后面的思路&#xff0c;具体实现等下周再开始详细写。 贪心算法 这个图非常好 122.买卖股票的最佳时机 II(妙&#xff0c;拆分利润) 把利润分解为每天为单位的维度&#xff0c;需要收集每天的正利润就可以&#xff0c;收集正利润的区间…

HarmonyOS ArkTS与C++数据类型转换

1. HarmonyOS ArkTS与C数据类型转换 本文介绍了C与TS各自数据类型与互相之间的数据类型转换&#xff0c;在需要使用C模块时可以快速上手对各种数据类型进行转换。 1.1. 概述 HarmonyOS的主力开发语言是ArkTS&#xff0c;也提供了C语言的支持&#xff0c;对于一些能力&#xff…

1.3 面向对象 C++面试问题

1.3.1 简述一下什么是面向对象,面向对象与面向过程的区别 什么是面向对象 面向对象&#xff08;Object-Oriented Programming&#xff0c;OOP&#xff09;是一种编程范式&#xff0c;它通过将现实世界中的实体抽象为“对象”来组织代码。面向对象编程关注对象及其交互&#x…

D51【python 接口自动化学习】- python基础之模块与标准库

day51 模块的导入 学习日期&#xff1a;20241027 学习目标&#xff1a;模块与标准库 -- 66 模块的导入&#xff1a;如何使用其他人编写好的代码功能&#xff1f; 学习笔记 模块的作用 导入模块的方法 # 导入模块 # 方式一 import os # 获取当前的位置 print(os.getcwd())# …

arduino uno R3更换328pb-au芯片,烧录bootloader

使用usbasp烧录器进行烧录&#xff0c;解压 【免费】usbsap驱动以及软件资源-CSDN文库 安装驱动 然后打开软件 界面如下 1按步骤选中芯片&#xff0c; ATmega328P&#xff08;由于没有328PB&#xff0c;直接选这个也行&#xff09; 2查看spi接线&#xff0c; 3读取芯片id&a…

【SpringCloud】07-分布式事务与Seata

1. 分布式事务 2. Seata 3. 安装seata 配置数据库 CREATE DATABASE IF NOT EXISTS seata /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTIONN */; USE seata;------------------------------- The script used when storeM…

加强版 第一节图像二值化定义

本节课介绍了图像又彩色图像转变为彩色图像转变为灰度图像转变为黑色图像的转化过程。 灰度图像-单通道-取值范围为0-255 二值图像-单通道-取值0&#xff08;黑色&#xff09;-255&#xff08;白色&#xff09; 二值分割 有五种分割方式 如图所示 第一种&#xff1a;大于…

RabbitMQ 高级特性——事务

文章目录 前言事务配置事务管理器加上Transactional注解 前言 前面我们学习了 RabbitMQ 的延迟队列&#xff0c;通过延迟队列可以实现生产者生产的消息不是立即被消费者消费。那么这篇文章我们将来学习 RabbitMQ 的事务。 事务 RabbitMQ 是基于 AMQP 协议实现的&#xff0c;…