当前位置: 首页 > news >正文

09 | JpaSpecificationExecutor 解决了哪些问题

QueryByExampleExecutor用法

QueryByExampleExecutor(QBE)是一种用户友好的查询技术,具有简单的接口,它允许动态查询创建,并且不需要编写包含字段名称的查询。

下面是一个 UML 图,你可以看到 QueryByExampleExecutor 是 JpaRepository 的父接口,也就是 JpaRespository 里面继承了 QueryByExampleExecutor 的所有方法。

Drawing 0.png

图一:Repository 类图

QBE 的基本语法

QBE 的基本语法可以分为下述几种。

复制代码

public interface QueryByExampleExecutor<T> { //根据“实体”查询条件,查找一个对象
<S extends T> S findOne(Example<S> example);
//根据“实体”查询条件,查找一批对象
<S extends T> Iterable<S> findAll(Example<S> example); 
//根据“实体”查询条件,查找一批对象,可以指定排序参数
<S extends T> Iterable<S> findAll(Example<S> example, Sort sort);//根据“实体”查询条件,查找一批对象,可以指定排序和分页参数 
<S extends T> Page<S> findAll(Example<S> example, Pageable pageable);
//根据“实体”查询条件,查找返回符合条件的对象个数
<S extends T> long count(Example<S> example); 
//根据“实体”查询条件,判断是否有符合条件的对象
<S extends T> boolean exists(Example<S> example); 
}

你可以看到这几个语法其实差不多,下面我们用 Page`` findAll 写一个分页查询的例子,看一下效果。

QueryByExampleExecutor 的使用案例

我们还用先前的 User 实体和 UserAddress 实体,并把 User 变丰富一点,这样方便测试。两个实体关键代码如下。

复制代码

@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString(exclude = "address")
public class User implements Serializable {@Id@GeneratedValue(strategy= GenerationType.AUTO)private Long id;private String name;private String email;@Enumerated(EnumType.STRING)private SexEnum sex;private Integer age;private Instant createDate;private Date updateDate;@OneToMany(mappedBy = "user",fetch = FetchType.EAGER,cascade = {CascadeType.ALL})private List<UserAddress> address;
}
enum SexEnum {BOY,GIRL
}
//User实体我们扩充了一些字段去了不同的类型,方便测试
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString(exclude = "user")
public class UserAddress {@Id@GeneratedValue(strategy= GenerationType.AUTO)private Long id;private String address;@ManyToOne(cascade = CascadeType.ALL)@JsonIgnoreprivate User user;
}
//UserAddress基本上不变

可以看出两个实体我们加了些字段。UserAddressRepository 继承 JpaRepository,从而也继承了 QueryByExampleExceutor 里面的方法,如下所示。

复制代码

public interface UserAddressRepository extends JpaRepository<UserAddress,Long> {
}

那么我们写一个测试用例,来熟悉一下 QBE 的语法,看一下完整的测试用例的写法。

复制代码

package com.example.jpa.example1;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.annotation.Rollback;
import javax.transaction.Transactional;
import java.time.Instant;
import java.util.Date;
@DataJpaTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class UserAddressRepositoryTest {@Autowiredprivate UserAddressRepository userAddressRepository;private Date now = new Date();/*** 负责添加数据,假设数据库里面已经有的数据*/@BeforeAll@Rollback(false)@Transactionalvoid init() {User user = User.builder().name("jack").email("123456@126.com").sex(SexEnum.BOY).age(20).createDate(Instant.now()).updateDate(now).build();userAddressRepository.saveAll(Lists.newArrayList(UserAddress.builder().user(user).address("shanghai").build(),UserAddress.builder().user(user).address("beijing").build()));}@Test@Rollback(false)public void testQBEFromUserAddress() throws JsonProcessingException {User request = User.builder().name("jack").age(20).email("12345").build();UserAddress address = UserAddress.builder().address("shang").user(request).build();ObjectMapper objectMapper = new ObjectMapper();
//    System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(address)); //可以打印出来看看参数是什么
//创建匹配器,即如何使用查询条件ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("user.email", ExampleMatcher.GenericPropertyMatchers.startsWith()).withMatcher("address", ExampleMatcher.GenericPropertyMatchers.startsWith());Page<UserAddress> u = userAddressRepository.findAll(Example.of(address,exampleMatcher), PageRequest.of(0,2));System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(u));}
}

其中,方法 testQBEFromUserAddress 负责测试 QBE,那么假设我们要写 API 的话,前端给我们的查询参数如下。

复制代码

{"id" : null,"address" : "shang","user" : {"id" : null,"name" : "jack","email" : "12345","sex" : null,"age" : 20,"createDate" : null,"updateDate" : null}
}

想要满足 email 前缀匹配、地址前缀匹配的动态查询条件,我们可以跑一下测试用例看一下结果。

复制代码

Hibernate: select useraddres0_.id as id1_2_, useraddres0_.address as address2_2_, useraddres0_.user_id as user_id3_2_ from user_address useraddres0_ inner join user user1_ on useraddres0_.user_id=user1_.id where user1_.age=20 and (user1_.email like ? escape ?) and user1_.name=? and (useraddres0_.address like ? escape ?) limit ?
2020-09-20 23:04:24.391 TRACE 62179 --- [    Test worker] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [12345%]
2020-09-20 23:04:24.391 TRACE 62179 --- [    Test worker] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [CHAR] - [\]
2020-09-20 23:04:24.392 TRACE 62179 --- [    Test worker] o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [VARCHAR] - [jack]
2020-09-20 23:04:24.392 TRACE 62179 --- [    Test worker] o.h.type.descriptor.sql.BasicBinder      : binding parameter [4] as [VARCHAR] - [shang%]
2020-09-20 23:04:24.393 TRACE 62179 --- [    Test worker] o.h.type.descriptor.sql.BasicBinder      : binding parameter [5] as [CHAR] - [\]

其中我们可以看到,传进来的参数和最终执行的 SQL,还挺符合我们的预期的,所以我们也能得到正确响应的查询结果,如下图:

Drawing 1.png

也就是一个地址带一个 User 结果。

那么接下来我们分析一下 Example 这个参数,看看它具体的语法是什么。

Example 语法详解

关于 Example 的语法,我们直接看一下它的源码吧,比较简单。

复制代码

public interface Example<T> {static <T> Example<T> of(T probe) {return new TypedExample<>(probe, ExampleMatcher.matching());}static <T> Example<T> of(T probe, ExampleMatcher matcher) {return new TypedExample<>(probe, matcher);}//实体参数T getProbe();//匹配器ExampleMatcher getMatcher();//回顾一下我们上一课时讲解的类型,这个是返回实体参数的Class Type;@SuppressWarnings("unchecked")default Class<T> getProbeType() {return (Class<T>) ProxyUtils.getUserClass(getProbe().getClass());}
}

而 TypedExample 这个类不是 public 的,看如下源码。

复制代码

@ToString
@EqualsAndHashCode
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
@Getter
class TypedExample<T> implements Example<T> {private final @NonNull T probe;private final @NonNull ExampleMatcher matcher;
}

其中我们发现三个类:Probe、ExampleMatcher 和 Example,分别做如下解释:

  • Probe:这是具有填充字段的域对象的实际实体类,即查询条件的封装类(又可以理解为查询条件参数),必填。
  • ExampleMatcher:ExampleMatcher 有关如何匹配特定字段的匹配规则,它可以重复使用在多个实例中,必填。
  • Example:Example 由 Probe 探针和 ExampleMatcher 组成,它用于创建查询,即组合查询参数和参数的匹配规则。

通过 Example 的源码,我们发现想创建 Example 的话,只有两个方法:

  1. static Example of(T probe):需要一个实体参数,即查询的条件。而里面的 ExampleMatcher 采用默认的 ExampleMatcher.matching(); 表示忽略 Null,所有字段采用精准匹配。
  2. static Example of(T probe, ExampleMatcher matcher):需要两个参数构建 Example,也就表示了 ExampleMatcher 自由组合规则,正如我们上面的测试用例里面的代码一样。

那么现在又遇到个类:ExampleMatcher,我们分析一下它的语法。

ExampleMatcher 语法分析

我们通过分析 ExampleMatcher 的源码来分析一下其用法。

首先打开 Structure 视图,看看里面对外暴露的方法都有哪些。

Drawing 2.png

通过 Structure 视图可以很容易地发现,我们要关心的方法都是这些 public 类型的返回 ExampleMatcher 的方法,那么我们把这些方法搞明白了是不是就可以掌握其详细用法了呢?下面看看它的实现类。

Drawing 3.png

TypedExampleMatcher 不是 public 类型的,所以我们可以基本上不用看了,主要看一下接口里面给我们暴露了哪些实例化方法。

初始化 ExampleMatcher 实例的方法

查看初始化 ExampleMatcher 实例的方法时,我们发现只有如下三个。

先看一下前两个方法:

复制代码

//默认matching方法
static ExampleMatcher matching() {return matchingAll();
}
//matchingAll,默认的方法
static ExampleMatcher matchingAll() {return new TypedExampleMatcher().withMode(MatchMode.ALL);
}

我们看到上面的两个方法所表达的意思是一样的,只不过一个是默认,一个是方法名上面有语义的。两者采用的都是 MatchMode.ALL 的模式,即 AND 模式,生成的 SQL 为如下形式:

复制代码

Hibernate: select useraddres0_.id as id1_2_, useraddres0_.address as address2_2_, useraddres0_.user_id as user_id3_2_ from user_address useraddres0_ inner join user user1_ on useraddres0_.user_id=user1_.id where user1_.age=20 and user1_.name=? and (user1_.email like ? escape ?) and (useraddres0_.address like ? escape ?) limit ?

可以看到,这些查询条件之间都是 AND 的关系。

我们再看一下方法三:

复制代码

static ExampleMatcher matchingAny() {return new TypedExampleMatcher().withMode(MatchMode.ANY);
}

第三个方法和前面两个方法的区别在于:第三个 MatchMode.ANY,表示查询条件是 or 的关系,我们看一下 SQL:

复制代码

Hibernate: select count(useraddres0_.id) as col_0_0_ from user_address useraddres0_ inner join user user1_ on useraddres0_.user_id=user1_.id where useraddres0_.address like ? escape ? or user1_.age=20 or user1_.email like ? escape ? or user1_.name=?

以上就是三个初始化 ExampleMatcher 实例的方法,你在运用中需要注意 and 和 or 的关系。
那么,我们再看一下 ExampleMatcher 语法给我们暴露的方法有哪些。

ExampleMatcher 语法给我们暴露的方法

忽略大小写

关于忽略大小写,我们看下代码:

复制代码

//默认忽略大小写的方式,默认 False。
ExampleMatcher withIgnoreCase(boolean defaultIgnoreCase);
//提供了一个默认的实现方法,忽略大小写;
default ExampleMatcher withIgnoreCase() {return withIgnoreCase(true);
}
//哪些属性的paths忽略大小写,可以指定多个参数;
ExampleMatcher withIgnoreCase(String... propertyPaths);

NULL 值的 property 怎么处理

暴露的 Null 值处理方式如下:

复制代码

ExampleMatcher withNullHandler(NullHandler nullHandler);

我们直接看参数 NullHandler枚举值即可,有两个可选值:INCLUDE(包括)、IGNORE(忽略),其中要注意:

  • 标识作为条件的实体对象中,一个属性值(条件值)为 Null 时,是否参与过滤;
  • 当该选项值是 INCLUDE 时,表示仍参与过滤,会匹配数据库表中该字段值是 Null 的记录;
  • 若为 IGNORE 值,表示不参与过滤。

复制代码

//提供一个默认实现方法,忽略 NULL 属性;
default ExampleMatcher withIgnoreNullValues() {return withNullHandler(NullHandler.IGNORE);
}
//把 NULL 属性值作为查询条件
default ExampleMatcher withIncludeNullValues() {return withNullHandler(NullHandler.INCLUDE);
}

到这里看一下,把 NULL 属性值作为查询条件,会执行什么样的 SQL:

复制代码

Hibernate: select useraddres0_.id as id1_2_, useraddres0_.address as address2_2_, useraddres0_.user_id as user_id3_2_ from user_address useraddres0_ inner join user user1_ on useraddres0_.user_id=user1_.id where (user1_.id is null) and (user1_.update_date is null) and user1_.age=20 and (user1_.create_date is null) and lower(user1_.name)=? and (lower(user1_.email) like ? escape ?) and (user1_.sex is null) and (lower(useraddres0_.address) like ? escape ?) and (useraddres0_.id is null) limit ?

这样就会导致我们一条数据都查不出来了。
忽略某些 Paths,不参加查询条件

复制代码

//忽略某些属性列表,不参与查询过滤条件。
ExampleMatcher withIgnorePaths(String... ignoredPaths);
字符串字段默认的匹配规则

复制代码

ExampleMatcher withStringMatcher(StringMatcher defaultStringMatcher);

关于默认字符串的匹配方式,枚举类型有 6 个可选值,DEFAULT(默认,效果同 EXACT)、EXACT(相等)、STARTING(开始匹配)、ENDING(结束匹配)、CONTAINING(包含,模糊匹配)、REGEX(正则表达式)。
字符串匹配规则,我们和 JPQL 对应到一起举例,如下表所示:

Drawing 4.png

相关代码如下:

复制代码

ExampleMatcher withMatcher(String propertyPath, GenericPropertyMatcher genericPropertyMatcher);

这里显示的是指定某些属性的匹配规则,我们看一下 GenericPropertyMatcher 是什么东西,它都提供了哪些方法。

如下图,基本可以看出来都是针对字符串属性提供的匹配规则,也就是可以通过这个方法定制不同属性的 StringMatcher 规则。

Drawing 5.png

到这里,语法部分我们就学习完了,下面看一个完整的例子感受一下。

完整的例子

下面是一个关于咱们上面所说的暴露的方法的使用的例子,你可以跟着我的步骤自己动手练习一下。

复制代码

//创建匹配器,即如何使用查询条件
ExampleMatcher exampleMatcher = ExampleMatcher//采用默认and的查询方式.matchingAll()//忽略大小写.withIgnoreCase()//忽略所有null值的字段.withIgnoreNullValues().withIgnorePaths("id","createDate")//默认采用精准匹配规则.withStringMatcher(ExampleMatcher.StringMatcher.EXACT)//级联查询,字段user.email采用字符前缀匹配规则.withMatcher("user.email", ExampleMatcher.GenericPropertyMatchers.startsWith())//特殊指定address字段采用后缀匹配.withMatcher("address", ExampleMatcher.GenericPropertyMatchers.endsWith());
Page<UserAddress> u = userAddressRepository.findAll(Example.of(address,exampleMatcher), PageRequest.of(0,2));

这时候可能会有同学问了,我是怎么知道默认值的呢?我们直接看类的构造方法就可以了,如下所示:

Drawing 6.png

从源码中我们可以看到,实现类的构造方法只有一个,就是“赋值默认”的方式。下面我整理了一些在使用这个语法时需要考虑的细节。

ExampleExceutor 使用中需要考虑的因素
  1. Null 值的处理:当某个条件值为 Null 时,是应当忽略这个过滤条件,还是应当去匹配数据库表中该字段值是 Null 的记录呢?
  2. 忽略某些属性值:一个实体对象,有许多个属性,是否每个属性都参与过滤?是否可以忽略某些属性?
  3. 不同的过滤方式:同样是作为 String 值,可能“姓名”希望精确匹配,“地址”希望模糊匹配,如何做到?

那么接下来我们分析一下源码看看其原理,说了这么半天,它到底和 JpaSpecificationExecutor 什么关系呢?我们接着看。

QueryByExampleExecutor 源码分析

怎么分析源码也很简单,我们看一下上面的我们 findAll 的方法调用之处。

Drawing 7.png

从而找到 findAll 方法的实现类,如下所示:

Drawing 8.png

通过 Debug 断点我们可以看到,我们刚才组合出来的 Example 对象,这个时候被封装成了 ExampleSpecification 对象,那么我们接着往下看方法里面的关键内容。

复制代码

TypedQuery<S> query = getQuery(new ExampleSpecification<>(example, escapeCharacter), probeType, pageable);

getQuery 方法是创建 Query 的关键,因为它里面做了条件的转化逻辑。那么我们再看一下参数 ExampleSpecification 的源码,发现它是接口 Specification 的实现类,并且是非公开的实现类,可以通过接口对外暴露 and、or、not、where 等组合条件的查询条件。

Drawing 9.png

我们接着看上面的 getQuery 方法的实现,可以看到接收的参数是 Specification``接口,所以不用关心实现类是什么。

Drawing 10.png

我们接着再看这个断点的 getQuery 方法:

Drawing 11.png

里面有一段代码会调用 applySpecificationToCriteria 生成 root,并由 Root 作为参数生成 Query,从而交给 EM(EntityManager)进行查询。

我们再来看一下关键的 applySpecificationToCriteria 方法。

Drawing 12.png

根据 Specification 调用 toPredicate 方法,生成 Predicate,从而实现查询需求。

现在我们已经对 QueryByExampleExecutor 的用法和实现原理基本掌握了,我们再来看一个十分相似的接口:JpaSpecificationExecutor 是干什么用的。

JpaSpecificationExecutor 接口结构

正如我们开篇提到的【图一:Repository 类图】,JpaSpecificationExecutor 是 JPA 里面的另一个接口分支。我们先来看看它的基本语法。

Drawing 13.png

我们通过查看 JpaSpecificationExecutor 的 Structure 图会发现,方法就有这么几个,细心的同学这个时候会发现它的参数 Specification,正是我们分析 QueryByExampleExecutor 的原理时候使用的 Specification。

那么 JpaSpecificationExecutor 帮我们解决了哪些问题呢?

JpaSpecificationExecutor 解决了哪些问题

  1. 我们通过 QueryByExampleExecutor 的使用方法和原理分析,不难发现,JpaSpecificationExecutor 的查询条件 Specification 十分灵活,可以帮我们解决动态查询条件的问题,正如 QueryByExampleExecutor 的用法一样;
  2. 它提供的 Criteria API 的使用封装,可以用于动态生成 Query 来满足我们业务中的各种复杂场景;
  3. 既然QueryByExampleExecutor 能利用 Specification 封装成框架,我们是不是也可以利用 JpaSpecificationExecutor 封装成框架呢?这样就学会了举一反三。

相关文章:

09 | JpaSpecificationExecutor 解决了哪些问题

QueryByExampleExecutor用法 QueryByExampleExecutor&#xff08;QBE&#xff09;是一种用户友好的查询技术&#xff0c;具有简单的接口&#xff0c;它允许动态查询创建&#xff0c;并且不需要编写包含字段名称的查询。 下面是一个 UML 图&#xff0c;你可以看到 QueryByExam…...

Linux命令(93)之su

linux命令之su 1.su介绍 linux命令su用于变更为其它使用者的身份&#xff0c;如root用户外&#xff0c;需要输入使用者的密码 2.su用法 su [参数] user su参数 参数说明-c <command>执行指定的命令&#xff0c;然后切换回原用户-切换到目标用户的环境变量 3.实例 3…...

1.HTML-HTML解决中文乱码问题

题记 下面是html文件解决中文乱码的方法 方法一 在 HTML 文件的 <head> 标签中添加 <meta charset"UTF-8">&#xff0c;确保文件以 UTF-8 编码保存 <head> <meta charset"UTF-8"> <!-- 其他标签和内容 --> </head> --…...

Vue3 + Nodejs 实战 ,文件上传项目--实现拖拽上传

目录 1.拖拽上传的剖析 input的file默认拖动 让其他的盒子成为拖拽对象 2.处理文件的上传 处理数据 上传文件的函数 兼顾点击事件 渲染已处理过的文件 测试效果 3.总结 博客主页&#xff1a;専心_前端,javascript,mysql-CSDN博客 系列专栏&#xff1a;vue3nodejs 实战-…...

Windows:VS Code IDE安装ESP-IDF【保姆级】

物联网开发学习笔记——目录索引 参考&#xff1a; VS Code官网&#xff1a;Visual Studio Code - Code Editing. Redefined 乐鑫官网&#xff1a;ESP-IDF 编程指南 - ESP32 VSCode ESP-ID Extension Install 一、前提条件 Visual Studio Code IDE安装ESP-IDF扩展&#xf…...

Hadoop3教程(十一):MapReduce的详细工作流程

文章目录 &#xff08;94&#xff09;MR工作流程Map阶段Reduce阶段 参考文献 &#xff08;94&#xff09;MR工作流程 本小节将展示一下整个MapReduce的全工作流程。 Map阶段 首先是Map阶段&#xff1a; 首先&#xff0c;我们有一个待处理文本文件的集合&#xff1b; 客户端…...

测试中Android与IOS分别关注的点

目录 1、自身不同点 2、测试注重点 3、其他测试点 主要从本身系统的不同点、系统造成的不同点、和注意的测试点做总结 1、自身不同点 研发商&#xff1a;Adroid是google公司做的手机系统&#xff0c;IOS是苹果公司做的手机系统   开源程度&#xff1a;Android是开源的&a…...

NLG(自然语言生成)评估指标介绍

诸神缄默不语-个人CSDN博文目录 本文介绍自然语言生成任务中的各种评估指标。 因为我是之前做文本摘要才接触到这一部分内容的&#xff0c;所以本文也是文本摘要中心。 持续更新。 文章目录 1. 常用术语2. ROUGE (Recall Oriented Understudy for Gisting Evaluation)1. 计算…...

苍穹外卖(七) Spring Task 完成订单状态定时处理

Spring Task 完成订单状态定时处理, 如处理支付超时订单 Spring Task介绍 Spring Task 是Spring框架提供的任务调度工具&#xff0c;可以按照约定的时间自动执行某个代码逻辑。 应用场景: 信用卡每月还款提醒 火车票售票系统处理未支付订单 入职纪念日为用户发送通知 点外…...

【探索Linux】—— 强大的命令行工具 P.11(基础IO,文件操作)

阅读导航 前言一、C语言的文件操作二、C的文件操作三、Linux系统文件操作&#xff08;I/O接口&#xff09;1. open()⭕传入多个打开方式&#xff08;按位或操作将不同的标志位组合在一起&#xff09; 2. write()3. read()4. close()5. lseek() 温馨提示 前言 前面我们讲了C语言…...

前端练习项目(附带页面psd图片及react源代码)

一、前言 相信很多学完前端的小伙伴都想找个前端项目练练手&#xff0c;检测自己的学习成果。但是现在很多项目市面上都烂大街了。今天给大家推荐一个全新的项目——电子校园 项目位置&#xff1a;https://github.com/v5201314/eSchool 二、项目介绍(部分页面展示)&#xff…...

【从零开始学习Redis | 第三篇】在Java中操作Redis

前言&#xff1a; 本文算是一期番外&#xff0c;介绍一下如何在Java中使用Reids &#xff0c;而其实基于Java我们有很多的开源框架可以用来操作redis&#xff0c;而我们今天选择介绍的是其中比较常用的一款&#xff1a;Spring Data Redis 目录 前言&#xff1a; Spring Data…...

vim、gcc/g++、make/Makefile、yum、gdb

vim、gcc/g、make/Makefile、yum、gdb 一、Linux编辑器vim1、简介2、三种模式的概念&#xff08;1&#xff09;正常/普通/命令模式(Normal mode)&#xff08;2&#xff09;插入模式(Insert mode)&#xff08;3&#xff09;末行/底行模式(last line mode) 3、三种模式的切换4、正…...

2022最新版-李宏毅机器学习深度学习课程-P13 局部最小值与鞍点

一、优化失败的原因 局部最小值&#xff1f;鞍点&#xff1f; 二、数学推导分析 用泰勒公式展开 一项与梯度&#xff08;L的一阶导&#xff09;有关&#xff0c;一项与海赛矩阵&#xff08;L的二阶导&#xff09;有关 海瑟矩阵 VTHV通过海瑟矩阵的性质可以转为判断H是否是正…...

ARM架构的基本知识

ARM两种授权 体系结构授权, 一种硬件规范, 用来约定指令集, 芯片内部体系结构(内存管理, 高速缓存管理), 只约定每一条指令的格式, 行为规范, 参数, 客户根据这个规范自行设计与之兼容的处理器处理IP授权, ARM公司根据某个版本的体系结构设计处理器, 再把处理器设计方案授权给…...

网络安全(黑客技术)——如何高效自学

前言 前几天发布了一篇 网络安全&#xff08;黑客&#xff09;自学 没想到收到了许多人的私信想要学习网安黑客技术&#xff01;却不知道从哪里开始学起&#xff01;怎么学&#xff1f;如何学&#xff1f; 今天给大家分享一下&#xff0c;很多人上来就说想学习黑客&#xff0c…...

云原生场景下高可用架构的最佳实践

作者&#xff1a;刘佳旭&#xff08;花名&#xff1a;佳旭&#xff09;&#xff0c;阿里云容器服务技术专家 引言 随着云原生技术的快速发展以及在企业 IT 领域的深入应用&#xff0c;云原生场景下的高可用架构&#xff0c;对于企业服务的可用性、稳定性、安全性越发重要。通…...

图论-最短路径算法-弗洛伊德算法与迪杰斯特拉算法

弗洛伊德算法&#xff1a; 弗洛伊德算法本质是动态规划&#xff0c;通过添加点进如可选择的点组成的集合的同时更新所有点之间的距离&#xff0c;从而得到每两个点之间的最短距离。 初始化&#xff1a; 创建一个二维数组 dist&#xff0c;其中 dist[i][j] 表示从节点 i 到节点…...

[23] IPDreamer: Appearance-Controllable 3D Object Generation with Image Prompts

pdf Text-to-3D任务中&#xff0c;对3D模型外观的控制不强&#xff0c;本文提出IPDreamer来解决该问题。在NeRF Training阶段&#xff0c;IPDreamer根据文本用ControlNet生成参考图&#xff0c;并将参考图作为Zero 1-to-3的控制条件&#xff0c;用基于Zero 1-to-3的SDS损失生成…...

深入理解React中的useEffect钩子函数

引言&#xff1a; React是一种流行的JavaScript库&#xff0c;它通过组件化和声明式编程的方式简化了前端开发。在React中&#xff0c;一个核心概念是组件的生命周期&#xff0c;其中包含了许多钩子函数&#xff0c;用于管理组件的不同阶段。其中之一就是useEffect钩子函数&…...

数字化时代的财务管理:挑战与机遇

导语&#xff1a;随着数字化技术的不断发展&#xff0c;财务管理正面临着前所未有的挑战和机遇。数字化不仅改变了财务数据的收集、处理和分析方式&#xff0c;还为财务决策提供了更多的依据和方向。本文将探讨数字化时代财务管理的新特点&#xff0c;以及如何利用数字化技术提…...

网络通信协议-HTTP、WebSocket、MQTT的比较与应用

在今天的数字化世界中&#xff0c;各种通信协议起着关键的作用&#xff0c;以确保信息的传递和交换。HTTP、WebSocket 和 MQTT 是三种常用的网络通信协议&#xff0c;它们各自适用于不同的应用场景。本文将比较这三种协议&#xff0c;并探讨它们的主要应用领域。 HTTP&#xff…...

【深度学习】深度学习实验四——循环神经网络(RNN)、dataloader、长短期记忆网络(LSTM)、门控循环单元(GRU)、超参数对比

一、实验内容 实验内容包含要进行什么实验,实验的目的是什么,实验用到的算法及其原理的简单介绍。 1.1 循环神经网络 (1)理解序列数据处理方法,补全面向对象编程中的缺失代码,并使用torch自带数据工具将数据封装为dataloader。 (2)分别采用手动方式以及调用接口方式…...

DB2分区表详解

一、分区表基本概念 当表中的数据量不断增大,查询数据的速度就会变慢,应用程序的性能就会下降,这时就应该考虑对表进行分区。分区后的表称为分区表。 表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据在物理上存放到多个“表空间”(物理文件上),这样查询数据时…...

基本地址变换机构

基本地址变换机构&#xff1a;用于实现逻辑地址到物理地址转换的一组硬件机构。 关于页号页表的定义&#xff0c;放个本人的传送门 1.页表寄存器 基本地址变换机构可以借助进程的页表将逻辑地址转换为物理地址。 1.作用 通常会在系统中设置一个页表寄存器&#xff08;PTR&…...

以单颗CMOS摄像头重构三维场景,维悟光子发布单目红外3D成像模组

维悟光子近期发布全新单目红外3D成像模组,现可提供下游用户进行测试导入。通过结合微纳光学元件编码和人工智能算法解码,维悟光子单目红外3D成像模组采用单颗摄像头,通过单帧拍摄,可同时获取像素级配准的3D点云和红外图像信息,可被应用于机器人、生物识别等广阔领域。 市场…...

Jinja2模板注入 | python模板注入特殊属性 / 对象讲解

在进行模板利用的时候需要使用特殊的属性和对象进行利用&#xff0c;这里对这些特殊属性及方法进行讲解 以下实验输出python3版本为 3.10.4&#xff0c; python2版本为 2.7.13 特殊属性 __class__ 类实例上使用&#xff0c;它用于获取该实例对应的类__base__ 用于获取父类__mr…...

一致性公式证明

首先&#xff0c;假设存在两个不同的聚类假设 f 1 f^1 f1和 f 2 f^2 f2&#xff0c;它们在两个视角上的聚类结果分别为 y 1 ∈ { − 1 , 1 } n y^1\in\{-1,1\}^n y1∈{−1,1}n和 y 2 ∈ { − 1 , 1 } n y^2\in\{-1,1\}^n y2∈{−1,1}n。 证明一致性不等式&#xff1a; ​ …...

allegro中shape的一些基本操作(一)——添加和修改shape

添加shape 简单添加shape的方式有3种&#xff0c;如下图所示 点击选择相应的shape模式后可以在option面板中设置相应的shape参数&#xff08;这里不做过多介绍&#xff0c;里面可以设置shape的大小、静态或动态shape等参数&#xff09;&#xff0c;然后再用鼠标在相应的层上添…...

HBuilder创建uniapp默认项目导入uview(胎教)

1&#xff1a;更新HBuilder 建议更新 2&#xff1a;更新插件 我本人在没有更新插件的情况下报错了&#xff0c;找到了**这个大佬**解决问题&#xff0c;所以建议更新插件 先卸载uni-app&#xff08;Vue2&#xff09;编译 再重新安装 uni-app&#xff08;Vue2&#xff09;…...

张家口做网站的公司/宁波seo外包方案

python 读取文件函数 觉得有用的话,欢迎一起讨论相互学习~感谢莫烦老师 详情 读取文件内容 file.read() 使用 file.read() 能够读取到文本的所有内容. file open(my file.txt,r) contentfile.read() print(content) """" This is my first test. This is t…...

深圳商城网站制作/短链接

为何要使用同步&#xff1f; java允许多线程并发控制&#xff0c;当多个线程同时操作一个可共享的资源变量时&#xff08;如数据的增删改查&#xff09;&#xff0c;将会导致数据不准确&#xff0c;相互之间产生冲突&#xff0c;因此加入同步锁以避免在该线程没有完成操作之前被…...

南宁网站设计多少钱/有没有推广app的平台

Package gp in the OpenCASCADE eryar163.com China 一、简介 Introduction to Package gp gp是几何处理程序包&#xff08;Geometric Processor package&#xff09;&#xff0c;简称gp。包gp提供以下功能&#xff1a; 代数计算&#xff1b;如坐标计算、矩阵计算&#xff1b;…...

网站只显示一个网址/提高基层治理效能

转载请注明出处&#xff1a;http://blog.csdn.net/u010019717更全的内容请看我的游戏蛮牛地址&#xff1a;http://www.unitymanual.com/space-uid-18602.html &#xfeff;&#xfeff;属性 &#xff08;Attribute&#xff09;使用 Unity 的C#语言 &#xff0c;利用属性&#…...

网站建设 售后服务/资源猫

sqoop安装&#xff1a;安装在一台节点上就可以了。1.上传sqoop2.安装和配置在添加sqoop到环境变量将数据库连接驱动拷贝到$SQOOP_HOME/lib里3.使用 第一类&#xff1a;数据库中的数据导入到HDFS上sqoop import --connect jdbc:mysql://192.168.1.10:3306/user--username root -…...

网站建设行业新闻/百度小说搜索排行榜

1、 string str1; str2 //语法: str1.EndsWith(str2); __检测字串str1是否以字串str2结尾,返回布尔值.如: if(str1.EndsWith(str2)){ Response.Write("字串str1是以"str2"结束的"); } 2、 //语法:str1.Equals(str2); __检测字串str1是否与字串str2相等,返回…...