jooq 分页排序_将jOOQ与Spring结合使用:排序和分页

jooq 分页排序

JOOQ是一个库,可以帮助我们控制SQL。 它可以从我们的数据库生成代码,并允许我们使用其流畅的API来构建类型安全的数据库查询。

本教程前面的部分向我们介绍了如何配置应用程序的应用程序上下文,如何从数据库生成代码以及将CRUD操作添加到jOOQ存储库。

这次,我们将学习如何实现支持排序和分页的简单搜索功能。

让我们开始吧。

补充阅读:

  • 将jOOQ与Spring结合使用:配置是本教程的第一部分,它描述了您可以配置使用jOOQ的Spring应用程序的应用程序上下文。 您可以在不阅读本教程第一部分的情况下了解此博客文章,但是,如果您想在Spring支持的应用程序中真正使用jOOQ,建议您也阅读本教程的第一部分。
  • 将jOOQ与Spring结合使用:代码生成是本教程的第二部分,它描述了如何对数据库进行反向工程并创建代表不同数据库表,记录等的jOOQ查询类。 因为这些类是类型安全SQL查询的构建块, 所以建议您在阅读本博客文章之前阅读本教程的第二部分
  • 在Spring中使用jOOQ:CRUD描述了如何为管理待办事项的简单应用程序添加CRUD操作。 因为它涵盖了使用Spring创建jOOQ存储库所需的信息, 所以建议您在阅读此博客文章之前先阅读它

向Web层添加分页和排序支持

当我们实现必须同时支持分页和排序的搜索功能时,我们必须找出一种方法来向后端提供页码,页面大小,排序字段的名称和排序顺序。

我们当然可以实现一个支持此功能的组件,但它并不像听起来那么简单。 创建一个HandlerMethodArgumentResolver很容易,它可以从HTTP请求中找到此信息并将其转换为对象,然后将该对象作为方法参数传递给我们的控制器方法。 问题在于,存在许多“例外”情况,这使该任务非常棘手。 例如,

  • 如果从HTTP请求中找不到此信息,则必须回退到默认值。
  • 如果缺少所需的信息(例如,没有指定页面大小就给出了页码),我们必须退回到默认值或向REST API用户返回错误。

幸运的是,我们不必实现此组件。 Spring Data Commons项目具有一个组件 , 该组件从HTTP请求中提取分页和排序信息,并允许我们将该信息注入到控制器方法中。

让我们发现我们可以使用Maven获得Spring Data Commons二进制文件。

使用Maven获取所需的依赖关系

通过将以下依赖项声明添加到POM文件的依赖项部分,我们可以使用Maven获得所需的二进制文件:

<dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-commons</artifactId><version>1.7.1.RELEASE</version>
</dependency>

下一步是对示例应用程序的应用程序上下文配置进行一些更改。 让我们继续前进,找出我们必须进行的更改。

配置应用程序上下文

我们可以通过对应用程序上下文配置类进行简单的更改来启用Spring Data的Web分页支持,该类配置了示例应用程序的Web层。 我们必须使用@EnableSpringDataWebSupport批注来批注配置类。 这样可以确保所需的bean自动注册。

@EnableSpringDataWebSupport批注的API文档提供了有关使用此批注时注册的bean的更多信息。

WebAppContext类的相关部分如下所示:

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.web.config.EnableSpringDataWebSupport;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;@Configuration
@ComponentScan({"net.petrikainulainen.spring.jooq.common.controller","net.petrikainulainen.spring.jooq.todo.controller"
})
@EnableWebMvc
@EnableSpringDataWebSupport
public class WebAppContext extends WebMvcConfigurerAdapter {//Other methods are omitted for the sake of clarity
}

这就对了。 现在,我们对示例应用程序的应用程序上下文配置进行了必要的更改。 让我们找出如何在应用程序中使用Web分页支持。

使用网页分页

当我们想对查询结果进行排序和分页时,我们必须遵循以下步骤:

  1. 将分页和排序配置添加到HTTP请求。
  2. Pageable方法参数添加到控制器方法。

首先 ,我们可以使用以下请求参数将分页和排序配置添加到HTTP请求:

  • 页面请求参数指定请求的页码。
  • size request参数指定所请求页面的大小。
  • 排序请求参数指定用于对查询结果进行排序的属性。 此请求参数的此值必须遵循以下语法: property,property(,ASC | DESC) 。 如果未给出排序方向,则结果将按升序排序。 如果要切换排序顺序,则必须使用多个排序参数(例如?sort = title&sort = id,desc )。

其次 ,我们必须在我们的控制器方法中添加一个Pageable方法参数。 TodoController类的相关部分如下所示:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import javax.validation.Valid;
import java.util.List;@RestController
@RequestMapping("/api/todo")
public class TodoController {private final TodoCrudService crudService;private final TodoSearchService searchService;@Autowiredpublic TodoController(TodoCrudService crudService, TodoSearchService searchService) {this.crudService = crudService;this.searchService = searchService;}@RequestMapping(value = "/search", method = RequestMethod.GET)public List<TodoDTO> findBySearchTerm(@RequestParam("searchTerm") String searchTerm, Pageable pageable) {return searchService.findBySearchTerm(searchTerm, pageable);}
}

现在,我们可以将搜索功能添加到我们的jOOQ存储库中。 让我们找出这是如何完成的。

实施存储库层

我们要做的第一件事是向TodoService接口添加一个新的公共方法。 findBySearchTerm(String searchTerm,Pageable pageable)方法查找其标题或描述包含给定搜索词的待办事项,并按照作为方法参数给出的分页和排序配置返回查询结果。

TodoRepository接口的相关部分如下所示:

import org.springframework.data.domain.Pageable;import java.util.List;public interface TodoRepository {public List<Todo> findBySearchTerm(String searchTerm, Pageable pageable);//Other methods are omitted for the sake of clarity
}

此方法的实现有两个职责:

  1. 它必须找到标题或描述包含给定搜索词的待办事项。
  2. 它必须处理从Pageable对象中找到的排序和分页选项,并将它们转换为jOOQ可以理解的形式。

让我们继续前进,找出如何找到标题或描述包含给定搜索词的待办事项。

实施搜索查询

我们可以按照以下步骤实施搜索查询:

  1. findBySearchTerm(String searchTerm,Pageable pageable 方法添加到JOOQTodoRepository类。
  2. 使用@Transactional注释对方法进行注释,并将其readOnly属性的值设置为true。
  3. 通过执行以下步骤来实现findBySearchTerm()方法:
    1. 创建在我们的数据库查询中使用的like表达式。
    2. 通过调用DSLContext接口的selectFrom(Table table)方法来创建新的SELECT语句,并指定要从todos表中选择信息。
    3. 通过调用SelectWhereStep接口的where(Collection condition)方法来指定SELECT语句的WHERE子句。 通过执行以下步骤创建此方法的方法参数:
      1. 通过调用Field接口的likeIgnoreCase(String value)方法,为 todos表的descriptiontitle列创建相似的条件。 将like表达式作为方法参数传递。
      2. 通过使用Condition接口的or(Condition other)方法组合创建的类似条件。
    4. 通过调用ResultQuery接口的fetchInto(Class type)方法获取TodosRecord对象的列表。 传递TodosRecord.class对象作为方法参数。
    5. 通过调用私有的convertQueryResultsToModelObjects()方法,将TodosRecord对象的列表转换为Todo对象的列表。 此方法迭代TodosRecord对象的列表,并通过调用convertQueryResultToModelObject()方法将每个TodosRecord对象转换为Todo对象。 每个Todo对象都添加到一个列表中,当所有TodosRecord对象都处理完毕后 ,将返回该列表。
    6. 返回Todo对象的列表。

我们实现的源代码如下:

import org.jooq.DSLContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;import java.util.ArrayList;
import java.util.List;import static net.petrikainulainen.spring.jooq.todo.db.tables.Todos.TODOS;@Repository
public class JOOQTodoRepository implements TodoRepository {private final DateTimeService dateTimeService;private final DSLContext jooq;//The constructor is omitted for the sake of clarity@Transactional(readOnly = true)@Overridepublic List<Todo> findBySearchTerm(String searchTerm, Pageable pageable) {String likeExpression = "%" + searchTerm + "%";List<TodosRecord> queryResults = jooq.selectFrom(TODOS).where(TODOS.DESCRIPTION.likeIgnoreCase(likeExpression).or(TODOS.TITLE.likeIgnoreCase(likeExpression))).fetchInto(TodosRecord.class);return convertQueryResultsToModelObjects(queryResults);}private List<Todo> convertQueryResultsToModelObjects(List<TodosRecord> queryResults) {List<Todo> todoEntries = new ArrayList<>();for (TodosRecord queryResult : queryResults) {Todo todoEntry = convertQueryResultToModelObject(queryResult);todoEntries.add(todoEntry);}return todoEntries;}private Todo convertQueryResultToModelObject(TodosRecord queryResult) {return Todo.getBuilder(queryResult.getTitle()).creationTime(queryResult.getCreationTime()).description(queryResult.getDescription()).id(queryResult.getId()).modificationTime(queryResult.getModificationTime()).build();}//Other methods are omitted for the sake of clarity
}

此示例的数据库查询非常简单。 如果需要创建更复杂的数据库查询,则应阅读4.6节。 jOOQ参考手册的条件表达式 。 它描述了如何在数据库查询中使用条件表达式。

现在,我们已经创建了一个存储库方法,该方法从数据库中搜索待办事项。 下一步是对该数据库查询的查询结果进行排序。

查询结果排序

在对搜索查询的查询结果进行排序之前,我们必须了解如何从Pageable对象中获取数据库查询的排序选项。

  • 我们可以通过调用Pageable接口的getSort()方法来获得对Sort对象的引用。 该对象包含从HTTP请求中找到的排序选项。
  • 排序对象可以包含零个或多个排序选项。 Sort类的iterator()方法返回一个Iterator <Sort.Order>对象,当我们要处理数据库查询的每个排序选项时可以使用该对象。
  • Sort.Order类包含属性名称和排序方向 。

换句话说,我们必须满足以下要求:

  • 我们必须支持未指定排序选项的情况。
  • 我们必须支持一种情况,其中我们的查询结果通过使用多列进行排序。
  • 我们必须假设每个列都有自己的排序顺序。

我们可以通过对JOOQTodoRepository类进行以下更改来满足这些要求:

  1. 将私有的getTableField(String sortFieldName)方法添加到存储库类,并按照以下步骤实现此方法:
    1. 使用反射获得一个Field对象,该对象提供有关Todos对象的请求字段的信息。
    2. 如果找不到该字段或我们无法访问它,则抛出一个新的InvalidDataAccessApiUsageException
    3. 如果找到该字段,则将返回的Field对象转换为TableField对象,然后将其返回。
  2. 将私有的convertTableFieldToSortField(TableField tableField,Sort.Direction sortDirection)方法添加到存储库类,并通过以下步骤实现该方法:
    1. 如果此字段的排序顺序是升序,请调用Field接口的asc()方法并返回返回的对象。
    2. 否则,调用Field接口的desc()方法并返回返回的对象。
  3. 将私有的getSortFields(Sort sortSpecification)方法添加到存储库类,并通过以下步骤实现它:
    1. 创建一个包含SortField <?>对象的新Collection
    2. 如果找不到排序选项,则返回一个空的Collection对象。
    3. 迭代从作为方法参数给出的Sort对象中找到的Sort.Order对象,并按照以下步骤处理每个Sort.Order对象:
      1. 使用getTableField()convertTableFieldToSortField()方法将每个Sort.Order对象转换为SortField <?>对象。
      2. 将每个SortField <?>对象添加到在第一步中创建的Collection中。
    4. <?>的对象返回的的SortField 集合
  4. 请按照以下步骤对查询结果进行排序:
    1. 通过调用Pageable接口的getSort()方法来获取Sort对象。
    2. 通过调用getSortFields()方法获取Collection <SortField <?>>对象。 将Sort对象作为方法参数传递。
    3. 通过调用SelectSeekStepN接口的orderBy(Collection <?扩展SortField <?>>字段)方法来创建ORDER BY子句,并将Collection <SortField <?>>对象作为方法参数传递。

我们的实现的源代码如下所示(相关部分已突出显示):

import org.jooq.DSLContext;
import org.jooq.SortField;
import org.jooq.TableField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;import static net.petrikainulainen.spring.jooq.todo.db.tables.Todos.TODOS;@Repository
public class JOOQTodoRepository implements TodoRepository {private final DateTimeService dateTimeService;private final DSLContext jooq;//The constructor is omitted for the sake of clarity@Transactional(readOnly = true)@Overridepublic List<Todo> findBySearchTerm(String searchTerm, Pageable pageable) {String likeExpression = "%" + searchTerm + "%";List<TodosRecord> queryResults = jooq.selectFrom(TODOS).where(TODOS.DESCRIPTION.likeIgnoreCase(likeExpression).or(TODOS.TITLE.likeIgnoreCase(likeExpression))).orderBy(getSortFields(pageable.getSort())).fetchInto(TodosRecord.class);return convertQueryResultsToModelObjects(queryResults);}private Collection<SortField<?>> getSortFields(Sort sortSpecification) {Collection<SortField<?>> querySortFields = new ArrayList<>();if (sortSpecification == null) {return querySortFields;}Iterator<Sort.Order> specifiedFields = sortSpecification.iterator();while (specifiedFields.hasNext()) {Sort.Order specifiedField = specifiedFields.next();String sortFieldName = specifiedField.getProperty();Sort.Direction sortDirection = specifiedField.getDirection();TableField tableField = getTableField(sortFieldName);SortField<?> querySortField = convertTableFieldToSortField(tableField, sortDirection);querySortFields.add(querySortField);}return querySortFields;}private TableField getTableField(String sortFieldName) {TableField sortField = null;try {Field tableField = TODOS.getClass().getField(sortFieldName);sortField = (TableField) tableField.get(TODOS);} catch (NoSuchFieldException | IllegalAccessException ex) {String errorMessage = String.format("Could not find table field: {}", sortFieldName);throw new InvalidDataAccessApiUsageException(errorMessage, ex);}return sortField;}private SortField<?> convertTableFieldToSortField(TableField tableField, Sort.Direction sortDirection) {if (sortDirection == Sort.Direction.ASC) {return tableField.asc();}else {return tableField.desc();}}private List<Todo> convertQueryResultsToModelObjects(List<TodosRecord> queryResults) {List<Todo> todoEntries = new ArrayList<>();for (TodosRecord queryResult : queryResults) {Todo todoEntry = convertQueryResultToModelObject(queryResult);todoEntries.add(todoEntry);}return todoEntries;}private Todo convertQueryResultToModelObject(TodosRecord queryResult) {return Todo.getBuilder(queryResult.getTitle()).creationTime(queryResult.getCreationTime()).description(queryResult.getDescription()).id(queryResult.getId()).modificationTime(queryResult.getModificationTime()).build();}//The other methods are omitted for the sake of clarity
}

此解决方案有效,但会将我们的存储库层(和数据库)的实现细节泄漏给REST API的客户端。 我们可以通过为列名称指定一组允许的别名来避免这种情况,并实现一个转换组件,将这些别名转换为Todos类的字段名称。

但是,因为这会增加我们的存储库类的复杂性,所以我们不会这样做。

这实际上是泄漏抽象的一个很好的例子。 这个词最初是由Joel Spolsky推广的。 他“发明” 了泄漏抽象定律,该定律指出:

在某种程度上,所有非平凡的抽象都是泄漏的。

通过阅读jOOQ参考手册的4.3.2.9节 ORDER BY子句,可以获得有关ORDER BY子句的更多信息。

现在,我们在搜索查询中添加了排序支持。 让我们继续并通过向findBySearchTerm()方法添加分页支持来完成我们的搜索功能。

分页查询结果

通过将LIMIT .. OFFSET子句添加到数据库查询中,我们可以对搜索查询的查询结果进行分页。 我们可以通过对数据库查询的实现进行以下更改来做到这一点:

  1. 通过调用SelectLimitStep接口的limit(int NumberOfRows)方法指定返回的行数,并将页面大小传递给方法参数(您可以通过调用Pageable接口的getPageSize()方法来获取页面大小)。
  2. 通过调用SelectOffsetStep接口的offset(int offset)方法指定偏移量, 并将偏移量作为方法参数传递(您可以通过调用Pageable接口的getOffset()方法来获取偏移量)。

在对存储库方法进行了这些更改之后,存储库方法的源代码如下所示(突出显示了更改):

import org.jooq.DSLContext;
import org.jooq.SortField;
import org.jooq.TableField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;import static net.petrikainulainen.spring.jooq.todo.db.tables.Todos.TODOS;@Repository
public class JOOQTodoRepository implements TodoRepository {private final DateTimeService dateTimeService;private final DSLContext jooq;//The constructor is omitted for the sake of clarity@Transactional(readOnly = true)@Overridepublic List<Todo> findBySearchTerm(String searchTerm, Pageable pageable) {String likeExpression = "%" + searchTerm + "%";List<TodosRecord> queryResults = jooq.selectFrom(TODOS).where(TODOS.DESCRIPTION.likeIgnoreCase(likeExpression).or(TODOS.TITLE.likeIgnoreCase(likeExpression))).orderBy(getSortFields(pageable.getSort())).limit(pageable.getPageSize()).offset(pageable.getOffset()).fetchInto(TodosRecord.class);return convertQueryResultsToModelObjects(queryResults);}private Collection<SortField<?>> getSortFields(Sort sortSpecification) {Collection<SortField<?>> querySortFields = new ArrayList<>();if (sortSpecification == null) {return querySortFields;}Iterator<Sort.Order> specifiedFields = sortSpecification.iterator();while (specifiedFields.hasNext()) {Sort.Order specifiedField = specifiedFields.next();String sortFieldName = specifiedField.getProperty();Sort.Direction sortDirection = specifiedField.getDirection();TableField tableField = getTableField(sortFieldName);SortField<?> querySortField = convertTableFieldToSortField(tableField, sortDirection);querySortFields.add(querySortField);}return querySortFields;}private TableField getTableField(String sortFieldName) {TableField sortField = null;try {Field tableField = TODOS.getClass().getField(sortFieldName);sortField = (TableField) tableField.get(TODOS);} catch (NoSuchFieldException | IllegalAccessException ex) {String errorMessage = String.format("Could not find table field: {}", sortFieldName);throw new InvalidDataAccessApiUsageException(errorMessage, ex);}return sortField;}private SortField<?> convertTableFieldToSortField(TableField tableField, Sort.Direction sortDirection) {if (sortDirection == Sort.Direction.ASC) {return tableField.asc();}else {return tableField.desc();}}private List<Todo> convertQueryResultsToModelObjects(List<TodosRecord> queryResults) {List<Todo> todoEntries = new ArrayList<>();for (TodosRecord queryResult : queryResults) {Todo todoEntry = convertQueryResultToModelObject(queryResult);todoEntries.add(todoEntry);}return todoEntries;}private Todo convertQueryResultToModelObject(TodosRecord queryResult) {return Todo.getBuilder(queryResult.getTitle()).creationTime(queryResult.getCreationTime()).description(queryResult.getDescription()).id(queryResult.getId()).modificationTime(queryResult.getModificationTime()).build();}//Other methods are omitted for the sake of clarity
}

您可以对限制更多信息..阅读OFFSET条款部分4.3.2.10极限.. OFFSET的jOOQ参考手册的条款 。

如果您需要实现“永恒滚动”(如时间轴上的Facebook),则应考虑使用seek方法。 您可以从jOOQ网站获取有关此信息的更多信息:

  • 使用Seek方法使用jOOQ进行更快SQL分页
  • 使用键集进行更快SQL分页,续
  • SEEK子句@ jOOQ参考手册

就这些了。 让我们继续并总结从这篇博客文章中学到的知识。

摘要

现在,我们已经实现了支持排序和分页的搜索功能。 本教程教会了我们三件事:

  • 我们了解了如何使用Spring Data Commons项目的Web分页支持。
  • 我们学习了如何将ORDER BY子句添加到数据库查询中。
  • 我们学习了如何在数据库查询中添加LIMIT .. OFFSET子句。

本教程的下一部分描述了如何集成Spring Data JPA和jOOQ,更重要的是,为什么要这样做。

  • Github上提供了此博客文章的示例应用程序。

翻译自: https://www.javacodegeeks.com/2014/05/using-jooq-with-spring-sorting-and-pagination.html

jooq 分页排序

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

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

相关文章

工控交换机和工业级交换机是怎么区别的,具体有哪些区别?分别应用在什么领域?

最近&#xff0c;有很多客户朋友对于工控交换机和工业级交换机二者之间了解的不是很清楚&#xff0c;常常误认为二者都是一样的&#xff0c;其实&#xff0c;这是两个完全不同的概念&#xff0c;我们通常说的交换机一般都是指的以太网交换机(排除电信用的程控交换机)。接下来&a…

ZigBee模块通信协议的树形拓扑组网结构

Zigbee无线通信协议的树形拓扑包括Co-ordinator(zigbee模块-协调器)节点、多个Router(zigbee模块-路由器)和Enddevice(zigbee模块-协调器)节点。Co-ordinator(zigbee模块-协调器)连接多个Router(zigbee模块路由器)和Endbeevice(zigbee模块协调器)&#xff0c;并连接多个Router(…

[渝粤教育] 中国矿业大学 恋爱心理学 参考 资料

教育 -恋爱心理学-章节资料考试资料-中国矿业大学【】 随堂测试 1、【单选题】毛泽东作为马克思主义作家&#xff0c;关于爱情提出了哪种观点&#xff1f; A、男女之间是自然的关系 B、爱情是不可以强求的 C、爱的势力难以阻挡 D、爱情绝不是禁欲主义 参考资料【 】 2、【单选题…

固执己见的框架(例如Spring Boot)的危险。 求知代码反转

我们开发人员喜欢抽象。 没有它&#xff0c;我们将无法构建应用程序。 我们的编程学科甚至要求我们对抽象进行编码&#xff0c;并避免将我们的代码耦合到详细的实现。 但是&#xff0c;什么是适合您的应用程序的正确抽象呢&#xff1f; 可悲的是&#xff0c;抽象的选择确实来…

ZigBee模块无线通信组网结构技术之Mesh拓扑网状

zigbee模块通信技术Mesh组网络拓扑包括Co-ordinator(zigbee协调器)节点和多个Router(zigbee模块无线路由)节点和Enddevice(zigbee终端)节点。网络拓扑形式与树形拓扑形式大致相同&#xff1b;然而&#xff0c;根据树形结构&#xff0c;网络网络拓扑是一种拓扑形式&#xff0c;具…

非管理型工业交换机和管理型工业交换机的区别和选择

工业交换机专门为满足灵活多变的工业应用需求而设计&#xff0c;提供一种高性价比工业以太网通讯解决方案。而工业交换机也分为非管理型和管理型两种。那么&#xff0c;非管理型工业交换机和管理型工业交换机有什么区别&#xff0c;我们改如何选择呢?下面就来简单介绍下。 一…

[渝粤教育] 中国科学技术大学 化学实验安全知识 参考 资料

教育 -化学实验安全知识-章节资料考试资料-中国科学技术大学【】 课前必测&#xff01; 1、【单选题】本课程中课堂交流区得分占总得分的&#xff08; &#xff09; A、20% B、30% C、40% D、0 参考资料【 】 2、【单选题】在综合讨论区和老师答疑区发帖时&#xff0c;应注意讨…

亿佰特lora模块在距离测量和定位上的应用

亿佰特lora模块http://www.ebyte.com LoRa技术是Semtech公司采用并且推广的的一种基于扩频技术的超远距离无线传输方案&#xff0c;属于低功耗广域网&#xff08;Low Power Wide Area Network&#xff0c;LPWAN&#xff09;通信技术中的一种。LoRa技术不再受限于传输距离和功耗…

E19系列与E10系列lora扩频技术无线模块选型指南

成都亿佰特电子科技有限公司是一家专注于无线数传通信应用的公司&#xff0c;在射频领域有着丰富的经验&#xff0c;也研发出了很多经典的产品&#xff0c;比如典型的E19和E10系列。 1.E19系列介绍 图1 E19系列无线模块 E19系列有433/868/915MHz射频模块&#xff0c;功率有1W…

工业级交换机的功率和管理功能详解

工业级PoE供电交换机的设备在为一些基于IP的终端传输数据信号的同时&#xff0c;还能为此类设备提供灵活&#xff0c;可靠的电力&#xff0c;最大限度地降低成本。那么&#xff0c;你对工业级交换机的功率和管理功能是否有所了解呢&#xff1f;接下来我们就跟随飞畅科技的小编一…

[渝粤教育] 信阳师范学院 视听语言 参考 资料

教育 -视听语言-章节资料考试资料-信阳师范学院【】 第1章 单元作业 第1章 单元测验 1、【多选题】人类语言的呈现形式有&#xff1a; A、视觉形式 B、触觉形式 C、嗅觉形式 D、听觉形式 参考资料【 】 2、【多选题】视听语言的构成要素包括&#xff1a; A、听觉元素 B、视觉元…

CAN总线定义和can总线无线通信特点

什么是CAN总线&#xff1f; CAN是Controller Area Network 的缩写&#xff08;以下称为CAN&#xff09;&#xff0c;是ISO国际标准化的串行通信协议。在汽车车载产业中&#xff0c;出于对车载安全性、舒适性、方便性、低功耗、低成本等等的要求&#xff0c;各种各样的电子控制…

从Java应用程序中消除Null指针异常

这篇文章简要介绍了Java 8的最有用但“毫不费力”的功能。 程序员花了无尽的时间来尝试纠正最常见但最危险的错误之一-空指针异常。 空指针异常可能导致我们的应用程序意外中断&#xff0c;并且很难预先检测到。 在许多情况下&#xff0c;当我们使用外部库和API时&#xff0…

[渝粤教育] 南京交通职业技术学院 计算机基础 参考 资料

教育 -计算机基础-章节资料考试资料-南京交通职业技术学院【】 windows 基本操作单元作业 windows 基本操作单元测验 1、【单选题】在 Windows 界面中,当一个窗口最小化后,其位于( )&#xff61; A、菜单栏 B、标题栏 C、任务栏 D、工具栏 参考资料【 】 2、【单选题】Windows中…

工业级以太网交换机的应用领域有哪些?

由于工业环境对工业控制网络的可靠性要求非常高&#xff0c;要求工业以太网有很强的冗余功能&#xff0c;工业控制对通信的实时性要求很高&#xff0c;工业环境十分恶劣&#xff0c;往往要求工业以太网设备长时间运行在有强电磁干扰、剧烈震动、粉尘、超高温、或超低温的环境中…

无线通信模块定点传输-点对点的具体传输应用

近年来&#xff0c;随着射频技术、集成电路、自动控制、无线数据通讯技术的迅速发展&#xff0c;无线传输技术越来越多的被提及&#xff0c;当前的智慧城市、智慧农业、智慧工厂等都需要无线传输技术来支撑。以下主要介绍几种点对点的无线通信具体应用&#xff1a; 一、在油田…

[渝粤教育] 南京信息职业技术学院 模拟电子技术 参考 资料

教育 -模拟电子技术-章节资料考试资料-南京信息职业技术学院【】 随堂小测 1、【单选题】在本征半导体中&#xff0c;本征激发产生的载流子是&#xff08; &#xff09; A、只有自由电子 B、只有空穴 C、正负离子 D、自由电子和空穴 参考资料【 】 2、【单选题】当PN结的P区加电…

基于433M频率无线通信模块在评委台的无线传输应用

1.433M频段特点 在无线电领域中&#xff0c;我们可以把无线电的种类按照频段来划分&#xff0c;如170M&#xff0c;315M&#xff0c;433M和2.4G等&#xff0c;本文主要以433M来介绍。 433MHZ频段的无线传输特点是&#xff1a;433MHZ是我们国家的免申请段发射接收频率&#xff…

工业级以太网交换机跟普通商用网络交换机有啥区别?

最近很多朋友在采购交换机的时候&#xff0c;对于工业级交换机跟商用网络交换机二者之间区分不是很清楚&#xff0c;对于具体采购哪一种类型的交换机拿不定主意&#xff0c;接下来杭州飞畅科技的小编来为您详细分析下二者之间的区别&#xff0c;帮你来快速判断适合哪种类型的交…

[渝粤教育] 南京工业职业技术大学 传感与智能控制技术 参考 资料

教育 -传感与智能控制技术-章节资料考试资料-南京工业职业技术大学【】 随堂测验 1、【单选题】下列说法错误的是 A、传感器是实现自动检测和自动控制的首要环节让物体有了触觉、味觉和嗅觉 B、传感器的功能可替代人类5大感觉器官 C、传感器是获取自然和生产领域中信息的主要途…