mybatis-plus自动填充时间的配置类实现
mybatis-plus自动填充时间的配置类实现
在实际操作过程中,我们并不希望创建时间、修改时间这些来手动进行,而是希望通过自动化来完成,而
mybatis-plus
则也提供了自动填充功能
来实现这一操作,接下来,就来了解一下mybatis-plus
的自动填充功能是如何进行操作的。
文章目录
- mybatis-plus自动填充时间的配置类实现
- 1. 目标
- 2. 上代码
- 2.1. 代码目录
- 2.2. pom文件
- 2.4. MyMetaObjectHandler(重点)
- 2.5. MybatisAutoConfiguration
- 2.6. UserContextHolder
- 2.7. BaseEntity
- 2.8. User
- 3. 测试
- 3.1. insert(User)
- 3.2. update(User)
- 3.3. updateUpdateWrapper()更新失败
- 3.4. updateUpdateWrapper()更新失败
- 3.5. userServiceUpdateUpdateWrapper() 更新失败
- 3.6. userServiceUpdateLambdaUpdateWrapper() 更新失败
- 4. 改造上面测试更新失败的
- 4.1. 增加UpdateWapperAspect切面(重点)
- 4.2. 测试updateUpdateWrapper()更新成功
- 4.3. 测试updateUpdateWrapper()更新成功
- 4.4. userServiceUpdateUpdateWrapper() 更新成功
- 3.6. userServiceUpdateLambdaUpdateWrapper() 更新成功
- 5.总结
1. 目标
- 实现默认设置创建者id,创建者用户名,更新者id,更新者用户名,创建时间,更新时间
- 实现自定义字段birth_day 没有设置值的时候设置当前时间
- 实现自定义字段login_time没有设置值的时候更新设置当前时间
sql信息如下
drop table if exists liu_user;
CREATE TABLE `liu_user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`username` varchar(255) DEFAULT NULL COMMENT '名字',
`password` varchar(255) DEFAULT NULL COMMENT '密码',
`phone` varchar(255) DEFAULT NULL COMMENT '电话号码',
`birth_day` timestamp NULL COMMENT '出生时间',
`login_time` timestamp NULL COMMENT '登录时间',
`create_by` varchar(20) DEFAULT NULL COMMENT '创建者id',
`create_by_name` varchar(100) DEFAULT NULL COMMENT '创建者账号名',
`update_by` varchar(20) DEFAULT NULL COMMENT '更新者id',
`update_by_name` varchar(100) DEFAULT NULL COMMENT '更新者账号名',
`create_time` timestamp NULL COMMENT '创建时间',
`update_time` timestamp NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) COMMENT='用户表';
2. 上代码
2.1. 代码目录
2.2. pom文件
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Tag-单元测试 junit--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><!-- aop切面 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>transmittable-thread-local</artifactId><version>2.14.3</version></dependency><dependency><groupId>org.testng</groupId><artifactId>testng</artifactId><version>6.14.3</version></dependency><!-- Tag-单元测试 junit--><!-- Tag-mybatis plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version></dependency><!-- Tag-mybatis plus--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.28</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency>
2.3. yml配置
spring:datasource:# mysqldriver-class-name: com.mysql.jdbc.Driverusername: rootpassword: 123456url: jdbc:mysql://192.168.0.154:3306/bigdata_src1?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
mybatis-plus:mapper-locations: classpath*:com/liuhm/dao/mysqlmapper/*Mapper.xml# 实体扫描,多个package用逗号或者分号分隔type-aliases-package: com.liuhm.entityglobal-config:db-config:id-type: autofield-strategy: not_nulllogic-delete-value: 0logic-not-delete-value: 0banner: falseconfiguration:#sql日志打印log-impl: org.apache.ibatis.logging.stdout.StdOutImplmap-underscore-to-camel-case: truecache-enabled: falseserver:port: 9099
2.4. MyMetaObjectHandler(重点)
常规实现MetaObjectHandler
package com.liuhm.config;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.liuhm.config.context.UserContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.lang.reflect.Field;
import java.util.*;/*** @ClassName:SmMetaObjectHandler* @Description: 全局处理基本字段* @Author: liuhaomin* @Date: 2023/11/29 15:25*/
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {private final List<String> userIdFieldList = new ArrayList<>(Arrays.asList("createBy", "updateBy"));private final List<String> userNameFieldList = new ArrayList<>(Arrays.asList("createByName", "updateByName"));private final String updateBy = "updateBy";private final String updateByName = "updateByName";private final static String JAVA_LANG_OBJECT = "java.lang.object";@Overridepublic void insertFill(MetaObject metaObject){try {setDefaultValue(metaObject, Arrays.asList(FieldFill.INSERT, FieldFill.INSERT_UPDATE));} catch (Exception e) {log.warn("设置默认参数失败 {}");}}@Overridepublic void updateFill(MetaObject metaObject){try {setDefaultValue(metaObject, Arrays.asList(FieldFill.INSERT_UPDATE, FieldFill.UPDATE));} catch (Exception e) {log.warn("设置默认参数失败 {}");}}public void setDefaultValue(MetaObject metaObject, List<FieldFill> fieldFills){List<Field> declaredFields = new ArrayList<>();Class tempClass = metaObject.getOriginalObject().getClass();while(tempClass != null && !tempClass.getName().toLowerCase().equals(JAVA_LANG_OBJECT)){declaredFields.addAll(Arrays.asList(tempClass.getDeclaredFields()));tempClass = tempClass.getSuperclass();}String userId = UserContextHolder.getUserId();String userName = UserContextHolder.getUserName();Date date = new Date();String fieldName = null;Object val = null;for(Field declaredField : declaredFields){fieldName = declaredField.getName();val = getFieldValByName(fieldName, metaObject);TableField annotation = declaredField.getAnnotation(TableField.class);if (Objects.nonNull(annotation) && (fieldFills.contains(annotation.fill()))) {if (Objects.isNull(val)) {if (userIdFieldList.contains(fieldName) && Objects.nonNull(userId)) {val = userId;}if (userNameFieldList.contains(fieldName) && Objects.nonNull(userName)) {val = userName;}// 插入的时候符合条件的 为空设置值// 设置符合条件的默认时间if ("Date".equals(declaredField.getType().getSimpleName())) {val = date;}} else {// 更新if (updateBy.equals(fieldName) && Objects.nonNull(userId)) {val = userId;}if (updateByName.equals(fieldName) && Objects.nonNull(userName)) {val = userName;}}if(fieldFills.contains(FieldFill.INSERT_UPDATE) && fieldFills.contains(FieldFill.UPDATE)){// 设置符合条件的默认时间if ("Date".equals(declaredField.getType().getSimpleName())) {val = date;}}setFieldValByName(fieldName, val, metaObject);}}}}
2.5. MybatisAutoConfiguration
package com.liuhm.config;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;/*** mybatis 自动配置类** @author liuhaomin* @date 2023.11.16*/
@Configuration
@MapperScan("com.liuhm.dao.mapper*")
public class MybatisAutoConfiguration {
}
2.6. UserContextHolder
package com.liuhm.config.context;import com.alibaba.ttl.TransmittableThreadLocal;/*** 模拟用户获取用户名和用户信息 上下文 Holder*/
public class UserContextHolder {/*** 当前用户编号*/private static final ThreadLocal<String> USER_ID = new TransmittableThreadLocal<>();private static final ThreadLocal<String> USER_NAME = new TransmittableThreadLocal<>();/*** 获得用户编号。** @return 用户编号*/public static String getUserId() {return USER_ID.get();}public static void setUserId(String userId) {USER_ID.set(userId);}public static void clear() {USER_ID.remove();USER_NAME.remove();}public static String getUserName() {return USER_NAME.get();}public static void setUserName(String userName) {USER_NAME.set(userName);}
}
2.7. BaseEntity
package com.liuhm.entity;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;import java.io.Serializable;
import java.util.Date;/*** @ClassName:BaseEntity* @Description: 基础的类* @Author: liuhaomin* @Date: 2023/11/29 15:17*/@Data
public class BaseEntity implements Serializable {private static final long serialVersionUID = -995832545980280226L;/*** 创建时间*/@TableField(fill = FieldFill.INSERT)private Date createTime;/*** 最后更新时间*/@TableField(fill = FieldFill.INSERT_UPDATE)private Date updateTime;/*** 创建者,目前使用 User 的 id 编号*/@TableField(fill = FieldFill.INSERT)private String createBy;@TableField(fill = FieldFill.INSERT)private String createByName;/*** 更新者,目前使用 User 的 id 编号*/@TableField(fill = FieldFill.INSERT_UPDATE)private String updateBy;@TableField(fill = FieldFill.INSERT_UPDATE)private String updateByName;/*** 是否删除*/// @TableLogic// private Boolean deleted;}
2.8. User
package com.liuhm.entity;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;/*** @ClassName:User* @Description: User* @Author: liuhaomin* @Date: 2024/12/23 13:50*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "liu_user")
public class User extends BaseEntity {private static final long serialVersionUID = -1L;private Integer id;/*** 用户名*/private String username;/*** 密码*/private String password;/*** 电话号码*/private String phone;/*** 出生时间*/@TableField(fill = FieldFill.INSERT)private Date birthDay;/*** 登录时间*/@TableField(fill = FieldFill.UPDATE)private Date loginTime;
}
2.9. 其余简单的类
public interface UserService extends IService<User>
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService
public interface UserMapper extends BaseMapper<User>
3. 测试
3.1. insert(User)
- 实现默认设置创建者id,创建者用户名,更新者id,更新者用户名,创建时间,更新时间,birth_day 默认有数据
@Testpublic void insert(){String userId = "1";String userName = "admin";// 设置上下文模拟请求中的用户信息UserContextHolder.setUserId(userId);UserContextHolder.setUserName(userName);User user = new User();user.setUsername("admin");user.setPassword("123456");user.setPhone("15723219655");userMapper.insert(user);List<User> users = userMapper.selectList(null);log.info("users:{}", users);}
3.2. update(User)
- 更新者id,更新者用户名,更新时间,login_time 默认有数据
@Testpublic void update(){String userId = "2";String userName = "admin2";// 设置上下文模拟请求中的用户信息UserContextHolder.setUserId(userId);UserContextHolder.setUserName(userName);User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername, "admin"));user.setPassword("123456789");userMapper.updateById(user);List<User> users = userMapper.selectList(null);log.info("users:{}", users);}
3.3. updateUpdateWrapper()更新失败
- 更新者id,更新者用户名,更新时间,Password
- 更新失败
@Testpublic void updateUpdateWrapper(){String userId = "3";String userName = "admin3";// 设置上下文模拟请求中的用户信息UserContextHolder.setUserId(userId);UserContextHolder.setUserName(userName);userMapper.update(null, new UpdateWrapper<User>().lambda().set(User::getPassword,"963852741").eq(User::getUsername, "admin"));List<User> users = userMapper.selectList(null);log.info("updateUpdateWrapper:{}", users);}
3.4. updateUpdateWrapper()更新失败
- 更新者id,更新者用户名,更新时间,Password
- 更新失败
@Testpublic void updateLambdaUpdateWrapper(){String userId = "4";String userName = "admin4";// 设置上下文模拟请求中的用户信息UserContextHolder.setUserId(userId);UserContextHolder.setUserName(userName);userMapper.update(null, new LambdaUpdateWrapper<User>().set(User::getPassword,"963852741123465").eq(User::getUsername, "admin"));List<User> users = userMapper.selectList(null);log.info("updateLambdaUpdateWrapper:{}", users);}
3.5. userServiceUpdateUpdateWrapper() 更新失败
- 更新者id,更新者用户名,更新时间,Password
- 更新失败
@Testpublic void userServiceUpdateUpdateWrapper(){String userId = "5";String userName = "admin5";// 设置上下文模拟请求中的用户信息UserContextHolder.setUserId(userId);UserContextHolder.setUserName(userName);userService.update( new UpdateWrapper<User>().lambda().set(User::getPassword,"963852741").eq(User::getUsername, "admin"));List<User> users = userMapper.selectList(null);log.info("userServiceUpdateUpdateWrapper:{}", users);}
3.6. userServiceUpdateLambdaUpdateWrapper() 更新失败
- 更新者id,更新者用户名,更新时间,Password
- 更新失败
@Testpublic void userServiceUpdateLambdaUpdateWrapper(){String userId = "6";String userName = "admin6";// 设置上下文模拟请求中的用户信息UserContextHolder.setUserId(userId);UserContextHolder.setUserName(userName);userService.update( new LambdaUpdateWrapper<User>().set(User::getPassword,"963852741123465").eq(User::getUsername, "admin"));List<User> users = userMapper.selectList(null);log.info("userServiceUpdateLambdaUpdateWrapper:{}", users);}
4. 改造上面测试更新失败的
4.1. 增加UpdateWapperAspect切面(重点)
package com.liuhm.config.acpect;import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.liuhm.config.context.UserContextHolder;
import com.liuhm.entity.BaseEntity;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.Objects;/*** @ClassName:UpdateWapperAspect* @Description: 解决update(Wrapper updateWrapper),自动填充不生效问题* @Author: liuhaomin* @Date: 2024/2/19 9:19*/
@Aspect
@Component
@Slf4j
public class UpdateWapperAspect{@Pointcut("execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.update(..))")public void pointcut(){}@Around(value = "pointcut()")public Object around(ProceedingJoinPoint pjp){updateEntity(pjp);try {return pjp.proceed();} catch (Throwable e) {throw new RuntimeException(e);}}/*** 重写update(Wrapper<T> updateWrapper), 更新时自动填充不生效问题** @param pjp** @return*/private void updateEntity(ProceedingJoinPoint pjp){Object[] args = pjp.getArgs();if (args != null && args.length == 2) {if(args[0] != null){return;}Object arg = args[1];String userId = UserContextHolder.getUserId();String userName = UserContextHolder.getUserName();if (arg instanceof UpdateWrapper) {UpdateWrapper updateWrapper = (UpdateWrapper) arg;String sqlSet = updateWrapper.getSqlSet();if(!sqlSet.contains("update_time")){updateWrapper.set("update_time", new Date());}if (Objects.nonNull(userId) && !sqlSet.contains("update_by")) {updateWrapper.set("update_by", userId);}if (Objects.nonNull(userName) && !sqlSet.contains("update_by_name")) {updateWrapper.set("update_by_name", userName);}}if (arg instanceof LambdaUpdateWrapper) {LambdaUpdateWrapper<BaseEntity> updateWrapper = (LambdaUpdateWrapper) arg;String sqlSet = updateWrapper.getSqlSet();if(!sqlSet.contains("update_time")){updateWrapper.set(BaseEntity::getUpdateTime, new Date());}if (Objects.nonNull(userId) && !sqlSet.contains("update_by")) {updateWrapper.set(BaseEntity::getUpdateBy, userId);}if (Objects.nonNull(userName) && !sqlSet.contains("update_by_name")) {updateWrapper.set(BaseEntity::getUpdateByName, userName);}}}}
}
4.2. 测试updateUpdateWrapper()更新成功
- 更新者id,更新者用户名,更新时间,Password
@Testpublic void updateUpdateWrapper(){String userId = "3";String userName = "admin3";// 设置上下文模拟请求中的用户信息UserContextHolder.setUserId(userId);UserContextHolder.setUserName(userName);userMapper.update(null, new UpdateWrapper<User>().lambda().set(User::getPassword,"963852741").eq(User::getUsername, "admin"));List<User> users = userMapper.selectList(null);log.info("updateUpdateWrapper:{}", users);}
4.3. 测试updateUpdateWrapper()更新成功
- 更新者id,更新者用户名,更新时间,Password
@Testpublic void updateLambdaUpdateWrapper(){String userId = "4";String userName = "admin4";// 设置上下文模拟请求中的用户信息UserContextHolder.setUserId(userId);UserContextHolder.setUserName(userName);userMapper.update(null, new LambdaUpdateWrapper<User>().set(User::getPassword,"963852741123465").eq(User::getUsername, "admin"));List<User> users = userMapper.selectList(null);log.info("updateLambdaUpdateWrapper:{}", users);}
4.4. userServiceUpdateUpdateWrapper() 更新成功
- 更新者id,更新者用户名,更新时间,Password
@Testpublic void userServiceUpdateUpdateWrapper(){String userId = "5";String userName = "admin5";// 设置上下文模拟请求中的用户信息UserContextHolder.setUserId(userId);UserContextHolder.setUserName(userName);userService.update( new UpdateWrapper<User>().lambda().set(User::getPassword,"963852741").eq(User::getUsername, "admin"));List<User> users = userMapper.selectList(null);log.info("userServiceUpdateUpdateWrapper:{}", users);}
3.6. userServiceUpdateLambdaUpdateWrapper() 更新成功
- 更新者id,更新者用户名,更新时间,Password
@Testpublic void userServiceUpdateLambdaUpdateWrapper(){String userId = "6";String userName = "admin6";// 设置上下文模拟请求中的用户信息UserContextHolder.setUserId(userId);UserContextHolder.setUserName(userName);userService.update( new LambdaUpdateWrapper<User>().set(User::getPassword,"963852741123465").eq(User::getUsername, "admin"));List<User> users = userMapper.selectList(null);log.info("userServiceUpdateLambdaUpdateWrapper:{}", users);}
5.总结
实现默认设置创建者id,创建者用户名,更新者id,更新者用户名,创建时间,更新时间
自定义mapperXml sql暂时不会默认更新上述字段
博客地址
代码下载
下面的mybatis-plus-fieldfill
相关文章:

mybatis-plus自动填充时间的配置类实现
mybatis-plus自动填充时间的配置类实现 在实际操作过程中,我们并不希望创建时间、修改时间这些来手动进行,而是希望通过自动化来完成,而mybatis-plus则也提供了自动填充功能来实现这一操作,接下来,就来了解一下mybatis…...

Vite内网ip访问,两种配置方式和修改端口号教程
目录 问题 两种解决方式 结果 总结 preview.host preview.port 问题 使用vite运行项目的时候,控制台会只出现127.0.0.1(localhost)本地地址访问项目。不可以通过公司内网ip访问,其他团队成员无法访问,这是因为没…...

【星海随笔】删除ceph
cephadm shell ceph osd set noout ceph osd set norecover ceph osd set norebalance ceph osd set nobackfill ceph osd set nodown ceph osd set pause参考文献: https://blog.csdn.net/lyf0327/article/details/90294011 systemctl stop ceph-osd.targetyum re…...

HarmonyOS NEXT实战:自定义封装多种样式导航栏组件
涉及知识点和装饰器 ComponentV2,Local, Builder,BuilderParam,Extend, Require ,Param,Event等第三方库:ZRouter ,如项目中本来就用了ZRouter路由库,案例中…...

大数据面试笔试宝典之Flink面试
1.Flink 是如何支持批流一体的? F link 通过一个底层引擎同时支持流处理和批处理. 在流处理引擎之上,F link 有以下机制: 1)检查点机制和状态机制:用于实现容错、有状态的处理; 2)水印机制:用于实现事件时钟; 3)窗口和触发器:用于限制计算范围,并定义呈现结果的…...

pytorch整体环境打包安装到另一台电脑上
步骤一:安装conda-pack 首先利用 pip list 指令检查conda环境安装在哪里,在系统环境(base)下,于是我是使用的conda指令完成的。 # 使用Conda安装(如果已安装conda) conda install conda-pack …...

PostgreSQL 数据库连接
title: PostgreSQL 数据库连接 date: 2024/12/29 updated: 2024/12/29 author: cmdragon excerpt: PostgreSQL是一款功能强大的开源关系数据库管理系统,在现代应用中广泛应用于数据存储和管理。连接到数据库是与PostgreSQL进行交互的第一步,这一过程涉及到多个方面,包括连…...

【算法】复杂性理论初步
六、算法复杂性初步 重要的复杂性类 P P P 的定义 多项式时间内可解的问题 若 L ∈ P L∈P L∈P,则存在确定性多项式时间的图灵机 M M M,使得 M ( x ) 1 ⟺ x ∈ L M(x)1⟺x∈L M(x)1⟺x∈L N P NP NP 的定义 多项式时间内可验证验证解的正确性 &…...

HarmonyOS NEXT应用开发实战:免费练手的网络API接口分享
学习一项技能,最好也最快的办法就是直接动手实战。在实战中不断的总结经验和收获成就感。这里分享些好用且免费的网络API练手接口,这对于想要提升自己网络开发能力的开发者来说,无疑是极大的福音。今天,我将详细介绍一个API接口集…...

C++的第一个程序
前言 在学习c之前,你一定还记得c语言的第一个程序 当时刚刚开始进行语言学习 因此告诉到,仅仅需要记住就可以 #include <stdio.h>int main(){printf("Hello World");return 0; }而对于c中的第一个程序,似乎有所变化 C的…...
Java 中 Stream 流的使用详解
Java 中 Stream 流的使用详解 什么是 Stream? Stream 是 Java 8 引入的一种全新的操作集合的方式。它支持通过声明性方式对集合进行复杂的数据操作(如过滤、排序、聚合等),避免使用大量的 for 循环,提高代码的可读性…...

【UE5.3.2】生成vs工程并rider打开
Rider是跨平台的,UE也是,当前现在windows上测试首先安装ue5.3.2 会自动有右键的菜单: windows上,右键,生成vs工程 生成的结果 sln默认是vs打开的,我的是vs2022,可以open with 选择 rider :Rider 会弹出 RiderLink是什么插...
ssh免密码登陆配置
ssh 命令本身不支持直接在命令中带上密码,出于安全考虑,SSH 协议不允许将密码明文写在命令中。直接在命令行中输入密码是一种不推荐的做法,因为它会暴露密码,增加安全风险。 如果你希望实现自动化登录而不手动输入密码࿰…...
Hive之import和export使用详解
在hive-0.8.0后引入了import/export命令。 Export命令可以导出一张表或分区的数据和元数据信息到一个输出位置,并且导出数据可以被移动到另一个hadoop集群或hive实例,并且可以通过import命令导入数据。 当导出一个分区表,原始数据可能在hdf…...
数据库锁的深入探讨
数据库锁(Database Lock)是多用户环境中用于保证数据一致性和隔离性的机制。随着数据库系统的发展,特别是在高并发的场景下,锁的机制变得尤为重要。通过使用锁,数据库能够防止并发操作导致的数据冲突或不一致。本文将深…...
【每日学点鸿蒙知识】沉浸式状态栏、类似ref 属性功能属性实现、自定义对话框背景透明、RichEditor粘贴回调、自动滚动列表
1、HarmonyOS 沉浸式状态栏? 实现沉浸式状态栏功能时,能够实现,但是目前每个自定义组件都需要padding top 状态栏的高度才行,有办法实现统一设置吗?不需要每个自定义组件中都padding top 状态栏的高度? 暂…...

Hive刷分区MSCK
一、MSCK刷分区 我们平时通常是通过alter table add partition方式增加Hive的分区的,但有时候会通过HDFS put/cp命令或flink、flum程序往表目录下拷贝分区目录,如果目录多,需要执行多条alter语句,非常麻烦。Hive提供了一个"…...
在Ubuntu下通过Docker部署Mastodon服务器
嘿,朋友们,今天咱们来聊聊如何在Ubuntu上通过Docker部署Mastodon服务器。想要拥有自己的社交媒体平台?Mastodon就是个不错的选择!🌐🚀 Docker与Mastodon简介 Docker是一个开源的容器化平台,让…...

【EtherCATBasics】- KRTS C++示例精讲(2)
EtherCATBasics示例讲解 目录 EtherCATBasics示例讲解结构说明代码讲解 项目打开请查看【BaseFunction精讲】。 结构说明 EtherCATBasics:应用层程序,主要用于人机交互、数据显示、内核层数据交互等; EtherCATBasics.h : 数据定义…...
MYSQL无法被连接问题
如果您在尝试连接到MySQL服务器时遇到问题,以下描述了您可以采取的一些措施来纠正该问题。 确保服务器正在运行。如果没有,则客户端无法连接到它。例如,如果尝试连接到服务器失败并出现以下消息之一,则可能是服务器未运行…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...

排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
前端高频面试题2:浏览器/计算机网络
本专栏相关链接 前端高频面试题1:HTML/CSS 前端高频面试题2:浏览器/计算机网络 前端高频面试题3:JavaScript 1.什么是强缓存、协商缓存? 强缓存: 当浏览器请求资源时,首先检查本地缓存是否命中。如果命…...