这篇文章分享自国内优秀IT教育机构——【优锐课】。我们将讨论如何使用新规范Jakarta NoSQL在Jakarta EE上进行分页。
分页是将内容分成离散页面的过程。每个页面都有来自数据库的实体列表。分页允许从数据存储中检索大量元素到小块中,例如,它返回十页包含一百个项目,而不是在存储引擎中返回一千个。这篇文章将讨论如何使用新规范Jakarta NoSQL在Jakarta EE上进行分页。
这篇文章将结合使用MongoDB和Car实体来演示如何在Jakarta NoSQL API上进行分页。
服务器启动时,MongoDB数据库必须正在运行,因此你可以手动下载并安装它,也可以使用Docker映像,然后运行以下命令:
docker run -d --name mongodb-instance -p 27017:27017 mongodb
该项目是一个Java SE项目,具有通过maven运行的CDI 2.0和Jakarta NoSQL。因此,所有配置和依赖项都是pom.xml文件。Jakarta NoSQL项目已获得批准,但不是最终版本。因此,该示例使用SNAPSHOT版本。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<name>Artemis Demo using Java SE MongoDB with pagiantion</name>
<groupId>org.jnosql.artemis</groupId>
<artifactId>pagination</artifactId>
<version>0.1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.jnosql.artemis</groupId>
<artifactId>artemis-document</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jnosql.diana</groupId>
<artifactId>mongodb-driver</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se-shaded</artifactId>
<version>${weld.se.core.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse</groupId>
<artifactId>yasson</artifactId>
<version>${json.b.version}</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>oss.sonatype.org-snapshot</id>
<url>http://oss.sonatype.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</project>
Car 实体具有五个属性:id,provider,model,year和color。
import jakarta.nosql.mapping.Column;
import jakarta.nosql.mapping.Entity;
import jakarta.nosql.mapping.Id;
@Entity
public class Car {
@Id
private Long id;
@Column
private String provider;
@Column
private String model;
@Column
private Integer year;
@Column
private String color;
@Override
public String toString() {
return "Car{" +
"id=" + id +
", provider='" + provider + '\'' +
", model='" + model + '\'' +
", year=" + year +
", color='" + color + '\'' +
'}';
}
}
我们将使用Mockaroo生成汽车信息,然后将此JSON转换为Jakarta NoSQL插入查询。
insert Car {"_id":1,"provider":"Dodge","model":"Caravan","year":2006,"color":"Teal"}
insert Car {"_id":2,"provider":"Lamborghini","model":"Aventador","year":2012,"color":"Blue"}
insert Car {"_id":3,"provider":"Mitsubishi","model":"Pajero","year":1997,"color":"Green"}
insert Car {"_id":4,"provider":"Mazda","model":"Miata MX-5","year":2005,"color":"Mauv"}
insert Car {"_id":5,"provider":"Dodge","model":"Aries","year":1981,"color":"Blue"}
insert Car {"_id":6,"provider":"Ford","model":"Windstar","year":1995,"color":"Yellow"}
insert Car {"_id":7,"provider":"Subaru","model":"Impreza","year":1999,"color":"Purple"}
insert Car {"_id":8,"provider":"Plymouth","model":"Acclaim","year":1995,"color":"Khaki"}
insert Car {"_id":9,"provider":"Audi","model":"200","year":1990,"color":"Puce"}
insert Car {"_id":10,"provider":"Kia","model":"Spectra","year":2009,"color":"Crimson"}
insert Car {"_id":11,"provider":"Volkswagen","model":"Golf","year":2001,"color":"Crimson"}
insert Car {"_id":12,"provider":"Chevrolet","model":"Silverado 1500","year":2008,"color":"Indigo"}
insert Car {"_id":13,"provider":"Studebaker","model":"Avanti","year":1961,"color":"Turquoise"}
insert Car {"_id":14,"provider":"Audi","model":"100","year":1994,"color":"Purple"}
insert Car {"_id":15,"provider":"Ford","model":"Taurus","year":2003,"color":"Maroon"}
insert Car {"_id":16,"provider":"GMC","model":"Acadia","year":2010,"color":"Indigo"}
insert Car {"_id":17,"provider":"Toyota","model":"Camry Hybrid","year":2011,"color":"Violet"}
insert Car {"_id":18,"provider":"Buick","model":"Roadmaster","year":1996,"color":"Purple"}
insert Car {"_id":19,"provider":"Mercury","model":"Monterey","year":2006,"color":"Mauv"}
insert Car {"_id":20,"provider":"GMC","model":"Sierra","year":2010,"color":"Violet"}
我们将有一个查询提供程序,它读取NoSQL文件并返回查询列表。
import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;
@ApplicationScoped
class QuerySupplier implements Supplier<List<String>> {
private List<String> queries;
@PostConstruct
void init() throws IOException {
final URL resource = QuerySupplier.class.getClassLoader().getResource("cars.nosql");
this.queries = Files.readAllLines(Paths.get(resource.getFile()));
}
@Override
public List<String> get() {
return Collections.unmodifiableList(queries);
}
}
在第一个示例代码中,我们将插入查询,然后从数据库中选择所有查询。二十个元素是一个很小的数目,但是此查询对性能有危险。确实,使用相同的查询可能会返回数千。几个数据库设置了默认限制,例如Cassandra,它隐式定义了上万个元素。一万个仍然是一个庞大的数字,要么显示给用户,要么返回到REST应用程序中。因此,这浪费了内存,数据库和网络。
import jakarta.nosql.mapping.document.DocumentTemplate;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.function.Supplier;
import static jakarta.nosql.document.DocumentDeleteQuery.delete;
public class App {
public static void main(String[] args) throws IOException {
try (SeContainer container = SeContainerInitializer.newInstance().initialize()) {
DocumentTemplate template = container.select(DocumentTemplate.class).get();
Supplier<List<String>> querySupplier = container.select(QuerySupplier.class).get();
template.delete(delete().from("Car").build());
final List<String> queries = querySupplier.get();
queries.forEach(template::query);
final List<Car> cars = template.query("select * from Car order by provider asc");
System.out.println(cars.size());
}
}
private App() {
}
}
在Jakarta NoSQL,有一个表示分页的接口。有分页界面。
Pagination pagination = Pagination.page(1).size(2);
//it creates a pagination instance where it is the first page and each page has the size of two each one.
long pageNumber = pagination.getPageNumber();
Pagination next = pagination.next();
每个NoSQL API在允许分页的查询中都有专门的查询,例如DocumentQueryPagination和ColumnQueryPagination。因此,Java开发人员可以定义每个请求要返回的值的数量。
import jakarta.nosql.document.DocumentQuery;
import jakarta.nosql.mapping.Page;
import jakarta.nosql.mapping.Pagination;
import jakarta.nosql.mapping.document.DocumentQueryPagination;
import jakarta.nosql.mapping.document.DocumentTemplate;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
import java.util.List;
import java.util.function.Supplier;
import static jakarta.nosql.document.DocumentDeleteQuery.delete;
public class App2 {
public static void main(String[] args) {
try (SeContainer container = SeContainerInitializer.newInstance().initialize()) {
DocumentTemplate template = container.select(DocumentTemplate.class).get();
Supplier<List<String>> querySupplier = container.select(QuerySupplier.class).get();
template.delete(delete().from("Car").build());
final List<String> queries = querySupplier.get();
queries.forEach(template::query);
DocumentQuery query = DocumentQuery.select().from("Car").orderBy("provider").asc().build();
Pagination pagination = Pagination.page(1).size(2);
DocumentQueryPagination queryPagination = DocumentQueryPagination.of(query, pagination);
final Page<Car> page = template.select(queryPagination);
List<Car> cars = page.getContent();
System.out.println(cars.size());
final Page<Car> nextPage = page.next();
cars = nextPage.getContent();
System.out.println(cars.size());
}
}
private App2() {
}
}
结果是一个Page实例,在该实例中有一种方法可以返回下一页,因此可以返回以下内容。存储库接口还支持将值作为Page实例返回。
import jakarta.nosql.mapping.Page;
import jakarta.nosql.mapping.Pagination;
import jakarta.nosql.mapping.Repository;
import java.util.List;
public interface CarRepository extends Repository<Car, Long> {
List<Car> findByOrderByProvider(Pagination pagination);
Page<Car> findAll(Pagination pagination);
}
import jakarta.nosql.mapping.Page;
import jakarta.nosql.mapping.Pagination;
import jakarta.nosql.mapping.document.DocumentTemplate;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
import java.util.List;
import java.util.function.Supplier;
import static jakarta.nosql.document.DocumentDeleteQuery.delete;
public class App3 {
public static void main(String[] args) {
try (SeContainer container = SeContainerInitializer.newInstance().initialize()) {
DocumentTemplate template = container.select(DocumentTemplate.class).get();
CarRepository repository = container.select(CarRepository.class).get();
Supplier<List<String>> querySupplier = container.select(QuerySupplier.class).get();
template.delete(delete().from("Car").build());
final List<String> queries = querySupplier.get();
queries.forEach(template::query);
Pagination pagination = Pagination.page(1).size(2);
final Page<Car> page = repository.findAll(pagination);
List<Car> cars = page.getContent();
System.out.println(cars.size());
final Page<Car> nextPage = page.next();
cars = nextPage.getContent();
System.out.println(cars.size());
}
}
private App3() {
}
}
至关重要的一点是,开发人员可以将分页和Collection结合在一起,结果将使用该分页进行查询。
import jakarta.nosql.mapping.Pagination;
import jakarta.nosql.mapping.document.DocumentTemplate;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
import java.util.List;
import java.util.function.Supplier;
import static jakarta.nosql.document.DocumentDeleteQuery.delete;
public class App4 {
public static void main(String[] args) {
try (SeContainer container = SeContainerInitializer.newInstance().initialize()) {
DocumentTemplate template = container.select(DocumentTemplate.class).get();
CarRepository repository = container.select(CarRepository.class).get();
Supplier<List<String>> querySupplier = container.select(QuerySupplier.class).get();
template.delete(delete().from("Car").build());
final List<String> queries = querySupplier.get();
queries.forEach(template::query);
Pagination pagination = Pagination.page(1).size(2);
final List<Car> cars = repository.findByOrderByProvider(pagination);
System.out.println(cars.size());
}
}
private App4() {
}
}
在本文中,我们介绍了分页的概念,并解释了为什么当开发人员谈论性能时,分页对NoSQL数据库如此重要。
感谢阅读!