Spring-boot Mybatis-plus 实战应用

文章目录

  • 前言
  • 一、springBoot 集成mybatis-plus
    • 1.1 maven 引入依赖:
    • 1.2 配置数据源::
  • 二、使用:
    • 2.1 mysql 打印执行的sql 设置:
    • 2.2 分页查询:
    • 2.3 条件构造器:
      • 2.3.1 QueryWrapper 查询:
      • 2.3.2 UpdateWrapper 更新:
      • 2.3.3 LambdaQueryWrapper查询:
      • 2.3. LambdaUpdateWrapper 更新:
  • 三、插件的使用:
    • 3.1 自定义id 生成:
    • 3.2 逻辑删除:
    • 3.3 自动填充:
    • 3.4 执行sql打印:
      • 3.4.1 依赖:
      • 3.4.2 驱动修改:
      • 3.4.3 定义 py.properties 配置:
      • 3.4.4 可选项 idea 对sql 美化插件 :
    • 3.5 数据库安全保护:
    • 3.6 数据库乐观锁:
    • 3.7 代码生成器:
      • 3.7.1 springboot web 项目中 jar:
      • 3.7.2 定义业务类生成:
      • 3.7.3 运行业务类生成:
  • 总结:
  • 参考:


前言

Spring-boot 项目中引入了Mybatis-plus 后 应该怎样进行数据源的配置,怎样通过Mybatis-plus 的接口快速的实现CRUD。


一、springBoot 集成mybatis-plus

1.1 maven 引入依赖:

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId>
</dependency>

1.2 配置数据源::

@Configuration
public class MyConfig {@Beanpublic DataSource dataSource() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setUrl("jdbc:mysql://localhost:3406/mybatis?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useAffectedRows=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8");dataSource.setUsername("root");dataSource.setPassword("ddsoft");return dataSource;}@Beanpublic JdbcTemplate jdbcTemplate(DataSource dataSource) {return new JdbcTemplate(dataSource);}@Beanpublic DataSourceTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}@Beanpublic JdbcTemplate jdbcTemplate() {return new JdbcTemplate(dataSource());}@Beanpublic DataSourceTransactionManager transactionManager() {return new DataSourceTransactionManager(dataSource());}}

二、使用:

2.1 mysql 打印执行的sql 设置:

# mysql 日志
logging.level.root= info
logging.level.com.example.springdabaihua=debug

tip: Dao 层 使用Mapper 的crud 通常与sql 的crud 名字开头;service 使用通查我们不会直接引用Mapper 层,会使用service 层:service 通查有业务命名的开头 如 listXxx ,getXxx ;这些api 这里不在进行展开,可以通过官网CRUD接口了解;

2.2 分页查询:

定义分页的插件进行sql 的拦截:

/*** 添加分页插件*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//如果配置多个插件,切记分页最后添加//interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); 如果有多数据源可以不配具体类型 否则都建议配上具体的DbTypereturn interceptor;
})

业务层的分页:

@Test
public void testPage1() {IPage<TbUser> ipage = new Page<TbUser>(1, 2);IPage<TbUser> page = userService.page(ipage);System.out.println(page.getRecords());System.out.println(page.getPages());System.out.println(page.getTotal());
}

mapper 层的分页:

@Test
public void testPage2() {IPage<TbUser> ipage = new Page<TbUser>(1, 2);IPage<TbUser> page = userMapper.getPage(ipage);;System.out.println(page.getRecords());System.out.println(page.getPages());System.out.println(page.getTotal());
}public interface TbUserMapper extends BaseMapper<TbUser> {IPage<TbUser> getPage(IPage<?>page );
}
<?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="com.example.springdabaihua.mapper.TbUserMapper"><select id="getPage" resultType="com.example.springdabaihua.entity.TbUser">select * from  tb_user</select>
</mapper>

2.3 条件构造器:

在这里插入图片描述

2.3.1 QueryWrapper 查询:

@Test
public  void testWraaper1(){QueryWrapper<TbUser> wrapper = new QueryWrapper<>();
// select 可以限制列名wrapper.select("id","name").like("name","张");List<TbUser> list = userService.list(wrapper);list.stream().forEach(e->{System.out.println(e);});
}

2.3.2 UpdateWrapper 更新:

@Test
public void testWraaper2() {UpdateWrapper<TbUser> wrapper = new UpdateWrapper<>();wrapper.like("name", "1");wrapper.set("name", "赵六");userService.update(wrapper);}

2.3.3 LambdaQueryWrapper查询:

增加使用 Lambda 表达式,这样就不用收到传入列名

@Test 
public void testWraaper3() {LambdaQueryWrapper<TbUser> wrapper = new LambdaQueryWrapper<>();wrapper.select(TbUser::getId,TbUser::getName).like(TbUser::getName, "张");List<TbUser> list = userService.list(wrapper);list.stream().forEach(e -> {System.out.println(e);});
}

2.3. LambdaUpdateWrapper 更新:

增加使用 Lambda 表达式,这样就不用收到传入列名

@Test 
public void testWraaper4() {LambdaUpdateWrapper<TbUser> wrapper = new LambdaUpdateWrapper<>();wrapper.like(TbUser::getName, "赵");wrapper.set(TbUser::getName,"小李飞刀");userService.update(wrapper);}

三、插件的使用:

3.1 自定义id 生成:

定义id 生成:(分布式全局唯一id 的设置可以参考我博客中的其他文章 搜索关键字"分布式全局唯一id" 查看)

@Component
public class CustomIdGenerator implements IdentifierGenerator {@Overridepublic Long nextId(Object entity) {//可以将当前传入的class全类名来作为bizKey,或者提取参数来生成bizKey进行分布式Id调用生成.String bizKey = entity.getClass().getName();//根据bizKey调用分布式ID生成long id = ....;//返回生成的id值即可.return id;}
}

实体类中定义使用自定义id:

  @TableId(value = "id", type = IdType.ASSIGN_ID)private Integer id;

3.2 逻辑删除:

mysql 表中增加逻辑删除的字段
在这里插入图片描述
tip :支持所有数据类型(推荐使用 Integer,Boolean,LocalDateTime),如果数据库字段使用datetime,逻辑未删除值和已删除值支持配置为字符串null,另一个值支持配置为函数来获取值如now();

可以对单表字段进行设置:

 @TableLogic(value = "1",delval = "0")private Integer isDelete;

也可以进行全局配置:

mybatis-plus:global-config:db-config:logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)logic-delete-value: 1 # 逻辑已删除值(默认为 1)logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

tip :只对自动注入的 sql 起效( 对mybatis-plus 提供的api 结果,自己xml 写的不支持):

  • 插入: 不作限制
  • 查找: 追加 where 条件过滤掉已删除数据,如果使用 wrapper.entity 生成的 where 条件也会自动追加该字段
  • 更新: 追加 where 条件防止更新到已删除数据,如果使用 wrapper.entity 生成的 where 条件也会自动追加该字段
  • 删除: 转变为 更新

3.3 自动填充:

填充创建,更新 人和时间:注解填充字段 @TableField(… fill = FieldFill.INSERT) 生成器策略部分也可以配置
自定义填充:

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {log.info("start insert fill ....");this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)// 或者this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)// 或者this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)}@Overridepublic void updateFill(MetaObject metaObject) {log.info("start update fill ....");this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐)// 或者this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)// 或者this.fillStrategy(metaObject, "updateTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)}
}

填充时机:

public enum FieldFill {/*** 默认不处理*/DEFAULT,/*** 插入填充字段*/INSERT,/*** 更新填充字段*/UPDATE,/*** 插入和更新填充字段*/INSERT_UPDATE
}

3.4 执行sql打印:

3.4.1 依赖:

  <dependency><groupId>p6spy</groupId><artifactId>p6spy</artifactId><version>3.9.1</version></dependency>

3.4.2 驱动修改:

  datasource:driver-class-name: com.p6spy.engine.spy.P6SpyDriverurl: jdbc:p6spy:h2:mem:test

tip : driver-class-name 和 url 都增加了 p6spy

3.4.3 定义 py.properties 配置:

#3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
#3.2.1以下使用或者不配置
#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 实际驱动可多个
#driverlist=org.h2.Driver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2

效果:
在这里插入图片描述

3.4.4 可选项 idea 对sql 美化插件 :

在这里插入图片描述
美化后 打印出来的sql 会进行格式化显示,而不是只在一行显示;

注意

  • driver-class-name 为 p6spy 提供的驱动类
  • url 前缀为 jdbc:p6spy 跟着冒号为对应数据库连接地址
  • 打印出 sql 为 null,在 excludecategories 增加 commit
  • 批量操作不打印 sql,去除 excludecategories 中的 batch
  • 批量操作打印重复的问题请使用 MybatisPlusLogFactory (3.2.1 新增)
  • 该插件有性能损耗,不建议生产环境使用。

3.5 数据库安全保护:

对敏感的数据进行加密,如mysql 的连接,用户名,密码等:

public static void main(String[] args) {// 生成 16 位随机 AES 密钥String randomKey = AES.generateRandomKey();System.out.println("randomKey = " + randomKey);// 随机密钥加密String result = AES.encrypt("root", randomKey);System.out.println(result);
}

获得的randomKey 为加密的秘钥,通过改秘钥可以实现对敏感数据加密;
效果:
在这里插入图片描述

项目启动时完成对自定义的密文内容进行解密:
定义要解密的属性值注解:DecryptedValue

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DecryptedValue {String value() default "";
}

在要加密的字段增加 DecryptedValue 注解:

@Value("${spring.datasource.username}")
@DecryptedValue("spring.datasource.username")
private String userName;@Value("${spring.datasource.password}")
@DecryptedValue("spring.datasource.password")
private String passWord;

定义解密类:DataSourceDecryptionProcessor


import com.baomidou.mybatisplus.core.toolkit.AES;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;import java.lang.reflect.Field;@Component
public class DataSourceDecryptionProcessor implements BeanPostProcessor {@Value("${spring.datasource.key:xxxx}")private String dataSourceKey;private final Environment environment;public DataSourceDecryptionProcessor(Environment environment) {this.environment = environment;}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {Class<?> clazz = bean.getClass();do {for (Field field : clazz.getDeclaredFields()) {DecryptedValue decryptedValueAnnotation = AnnotationUtils.findAnnotation(field, DecryptedValue.class);if (decryptedValueAnnotation != null) {String propertyValue = environment.getProperty(decryptedValueAnnotation.value());if (!StringUtils.isEmpty(propertyValue)) {field.setAccessible(true);try {// 对加密的值进行解密处理String value = AES.decrypt(propertyValue, dataSourceKey);field.set(bean, value);} catch (IllegalAccessException e) {e.printStackTrace();}}}}clazz = clazz.getSuperclass();} while (clazz != null);return bean;}
}

3.6 数据库乐观锁:

添加插件:

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;
}

在实体类的字段上加上@Version注解:

@Version
private Integer version;

表中增加 version int 类型字段 ;
在这里插入图片描述

测试1 :

@Test
public void testLock() throws InterruptedException {CountDownLatch countDownLatch =new CountDownLatch(2);for (int i = 0; i < 2; i++) {int finalI = i;new Thread(()->{TbUser byId = userService.getById(860069891);byId.setName("lisi"+ finalI);try {Thread.sleep(2000);} catch (InterruptedException e) {countDownLatch.countDown();throw new RuntimeException(e);}userService.updateById(byId);countDownLatch.countDown();},"thread"+i).start();}countDownLatch.await();}

在这里插入图片描述
测试2 :

@Test
public void testLock1() throws InterruptedException {TbUser byId1 = userService.getById(860069891);TbUser byId2 = userService.getById(860069891);byId1.setName("张飞1");System.out.println("userService.updateById(byId1) = " + userService.updateById(byId1));byId2.setName("赵云1");System.out.println("userService.updateById(byId2) = " + userService.updateById(byId2));}

在这里插入图片描述

3.7 代码生成器:

用于快速生成 实体,service ,mapper 和controller ,方便业务开发;

3.7.1 springboot web 项目中 jar:

  <dependencies>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.18</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.1.1</version></dependency><!--代码生成器--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.1.1</version></dependency><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.28</version></dependency><!--代码生成器-->
</dependencies>

3.7.2 定义业务类生成:

package com.example.mybatiscodegenerage;import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.springframework.util.StringUtils;import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;public class GenerateCode {/*** <p>* 读取控制台内容* </p>*/public static String scanner(String tip) {Scanner scanner = new Scanner(System.in);StringBuilder help = new StringBuilder();help.append("请输入" + tip + ":");System.out.println(help.toString());if (scanner.hasNext()) {String ipt = scanner.next();if (StringUtils.hasText(ipt)) {return ipt;}}throw new MybatisPlusException("请输入正确的" + tip + "!");}public static void main(String[] args) {// 代码生成器AutoGenerator mpg = new AutoGenerator();// 全局配置GlobalConfig gc = new GlobalConfig();// 当前项目路径获取String projectPath = System.getProperty("user.dir");// 输出目录gc.setOutputDir(projectPath + "/spring-batch/src/main/java");// 设置作者gc.setAuthor("jobob");// 代码生成后是不是需要打开所在文件夹gc.setOpen(false);// 是否生成 Swagger2 注解// gc.setSwagger2(true); 实体属性 Swagger2 注解// 是否在xml 中生成映射所有字段的BaseResultMap//gc.setBaseResultMap(true);// 相同文件生成覆盖gc.setFileOverride(true);// 生成代码的时间格式gc.setDateType(DateType.ONLY_DATE);// https://baomidou.com/pages/061573/#datetype// 用表的名字直接生成实体,%s 表名 不加Entity 后缀// gc.setEntityName("%s");// Mapper 接口名 %sMapper 表名+Mapper//  gc.setMapperName("%sMapper");// Mapper.xml 生成文件名,表名+Mapper.xml// gc.setXmlName("%sMapper");//Service 接口名称 表名+ Service// gc.setServiceName("%sService")//Service 接口实现类名称 表名+ ImplService// gc.setServiceImplName("%sImplService");// 设置到全局配置中mpg.setGlobalConfig(gc);// 数据源配置DataSourceConfig dsc = new DataSourceConfig();dsc.setUrl("jdbc:mysql://localhost:3406/mybatis?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useAffectedRows=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8");// dsc.setSchemaName("public");
//        dsc.setDriverName("com.mysql.jdbc.Driver");dsc.setDriverName("com.mysql.cj.jdbc.Driver");dsc.setUsername("root");dsc.setPassword("ddsoft");mpg.setDataSource(dsc);// 包配置PackageConfig pc = new PackageConfig();// 如 com.xxx.xxx.user ,com.xxx.xxx 为包名, user 为模块名称// 设置模块名称pc.setModuleName(scanner("模块名"));// 设置包名字pc.setParent("com.baomidou.ant");mpg.setPackageInfo(pc);// 自定义配置 自定义属性InjectionConfig cfg = new InjectionConfig() {@Overridepublic void initMap() {// to do nothing}};// 如果模板引擎是 freemarkerString templatePath = "/templates/mapper.xml.ftl";// 如果模板引擎是 velocity// String templatePath = "/templates/mapper.xml.vm";// 自定义输出配置List<FileOutConfig> focList = new ArrayList<>();// 自定义配置会被优先输出 mapper.xml 文件位置设置focList.add(new FileOutConfig(templatePath) {@Overridepublic String outputFile(TableInfo tableInfo) {// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!return projectPath + "/spring-batch/src/main/resources/mapper/" + pc.getModuleName()+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;}});/*cfg.setFileCreate(new IFileCreate() {@Overridepublic boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {// 判断自定义文件夹是否需要创建checkDir("调用默认方法创建的目录,自定义目录用");if (fileType == FileType.MAPPER) {// 已经生成 mapper 文件判断存在,不想重新生成返回 falsereturn !new File(filePath).exists();}// 允许生成模板文件return true;}});*/// 设置自定义配置cfg.setFileOutConfigList(focList);mpg.setCfg(cfg);// 配置模板TemplateConfig templateConfig = new TemplateConfig();// 配置自定义输出模板//指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别// templateConfig.setEntity("templates/entity2.java");// templateConfig.setService();// templateConfig.setController();// 把 已有的生成在代码层面的xml 配置失效templateConfig.setXml(null);mpg.setTemplate(templateConfig);// 策略配置,数据库表配置StrategyConfig strategy = new StrategyConfig();//数据库表映射到实体的命名策略 下划线转驼峰strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体类的命名策略strategy.setColumnNaming(NamingStrategy.underline_to_camel);//自定义继承entity类,添加这一个会在生成实体类的时候继承entity//strategy.setSuperEntityClass("com.wy.testCodeGenerator.entity");//实体是否为lombok模型strategy.setEntityLombokModel(true);//生成@RestController控制器strategy.setRestControllerStyle(true);// 公共父类  Controller 是否有父类// strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");// 写于父类中的公共字段// strategy.setSuperEntityColumns("id");// 如果想按照前缀生成 setTablePrefix("pms_")
//        strategy.setTablePrefix("pms_");strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));// 驼峰转连字符串  RestController 中的mapper 路径设置 设置了则生成 表名的路径如 pmp_userstrategy.setControllerMappingHyphenStyle(true);// 表前缀 如 pms_xxx 生成的类就不带pms
//        strategy.setTablePrefix( "pms");strategy.setTablePrefix(pc.getModuleName() + "_");mpg.setStrategy(strategy);mpg.setTemplateEngine(new FreemarkerTemplateEngine());mpg.execute();}
}

3.7.3 运行业务类生成:

在这里插入图片描述


总结:

本文对Spring-boot Mybatis-plus 常用的CRUD api 及常用的插件进行整理。

参考:

Mybatis-plus 官网;

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

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

相关文章

【寒武纪(7)】MLU的cntoolkit:Cambricon-BANG架构和使用分析,MLU并行计算的硬件抽象、编程模型以及调优思路

文章目录 硬件抽象1存储1.1.1 存储层次访存一致 计算模型1 Core核内同步和并行2 核间并行和同步 编程模型1、Kernel计算规模 任务类型执行示例 性能调优性能调优实践参考 cambricon BANG架构是基础的&#xff0c;高度抽象的&#xff0c;向用户暴露统一编程模型和编程接口&#…

Kerberos认证系统

文章目录 前提知识原理第一次对话第二次对话第三次对话 总结发现 前提知识 KDC&#xff1a;由AS、TGS&#xff0c;还有一个Kerberos Database组成。 Kerberos Database用来存储用户的密码或者其他所有信息&#xff0c;请求的时候需要到数据库中查找。 AS&#xff1a;为客户端提…

语音识别芯片在产品应用上的难点列举

语音识别技术&#xff0c;作为人工智能领域中的一颗璀璨明珠&#xff0c;已经广泛应用于用户交互、智能家居、语音助手等多个领域。它为我们的生活带来了诸多便利&#xff0c;使得我们可以更加高效地与电子设备进行互动。然而&#xff0c;语音识别技术的实现&#xff0c;依赖于…

电脑篇——将串口映射到远程电脑上

通过Windows自带的远程桌面连接功能&#xff0c;可以通过修改本地资源选项&#xff0c;将本机的串口/端口映射到远程电脑上。 即可将端口映射到远程电脑上。 &#xff08;在远程的电脑的设备管理器中可能不会显示&#xff0c;但是用串口调试相关的工具&#xff0c;是可以找到相…

Linux 6.7 正式移除对英特尔 IA-64 架构安腾处理器的支持

导读随着 Linux 6.7 的到来&#xff0c;主流 Linux 内核将停止对 Intel Itanium&#xff08;IA-64&#xff09;处理器的支持。 实际上&#xff0c;Linux 近年来对于 Itanium 的支持一直在走下坡路&#xff0c;没有活跃用户&#xff0c;也没有活跃的主要贡献者来维护 Itanium 代…

数据库事务相关问题

1. 什么是数据库事务&#xff1f; 事务&#xff0c;由一个有限的数据库操作序列构成&#xff0c;这些操作要么全部执行,要么全部不执行&#xff0c;是一个不可分割的工作单位。 假如A转账给B 100 元&#xff0c;先从A的账户里扣除 100 元&#xff0c;再在 B 的账户上加上 100 …

Stable Diffusion WebUI使用AnimateDiff插件生成动画

AnimateDiff 可以针对各个模型生成的图片&#xff0c;一键生成对应的动图。 配置要求 GPU显存建议12G以上&#xff0c;在xformers或者sdp优化下显存要求至少6G以上。 要开启sdp优化&#xff0c;在启动参数加上--sdp-no-mem-attention 实际的显存使用量取决于图像大小&#…

麒麟KYLINOS中使用Ghost镜像文件还原系统

原文链接&#xff1a;麒麟KYLINOS中使用Ghost镜像文件还原系统 hello&#xff0c;大家好啊&#xff0c;今天给大家带来麒麟KYLINOS备份还原的第三篇文章&#xff0c;使用Ghost镜像文件还原系统&#xff0c;将之前做好的Ghost镜像文件拷贝到u盘里&#xff0c;然后在另一台终端上…

如何使用iPhone15在办公室观看家里电脑上的4k电影?

如何使用iPhone15在办公室观看家里电脑上的4k电影&#xff1f; 文章目录 如何使用iPhone15在办公室观看家里电脑上的4k电影&#xff1f;1.使用环境要求&#xff1a;2.下载群晖videostation&#xff1a;3.公网访问本地群晖videostation中的电影&#xff1a;4.公网条件下使用电脑…

智能导诊的开发技术有哪些?

智能导诊源码 智能导诊是医疗领域中一项重要的应用&#xff0c;它可以帮助医生和患者更快速、更准确地诊断疾病&#xff0c;提高医疗效率和精度。以下是智能导诊开发技术的几个方面: 1.数据收集整合 智能导诊系统需要收集大量的医疗数据&#xff0c;包括患者症状、病史、检查结…

栈:括号匹配问题!

目录 题目&#xff1a; 思路分析&#xff1a; 解题思路&#xff1a; 一、配对&#xff1a; 二、数量问题&#xff1a; 三、细节问题&#xff1a; 完整代码&#xff1a; 手撕栈&#xff1a; 题目&#xff1a; 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&…

基于布谷鸟算法优化概率神经网络PNN的分类预测 - 附代码

基于布谷鸟算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于布谷鸟算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于布谷鸟优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络…