1. Overview
1.概述
Eclipse JNoSQL is a set of APIs and implementations that simplify the interaction of Java applications with NoSQL databases.
Eclipse JNoSQL是一组API和实现,简化了Java应用程序与NoSQL数据库的交互。
In this article, we’ll learn how to set up and configure JNoSQL to interact with a NoSQL database. We’ll work with both the Communication and Mapping layer.
在这篇文章中,我们将学习如何设置和配置JNoSQL来与NoSQL数据库进行交互。我们将与通信和映射层一起工作。
2. Eclipse JNoSQL Communication Layer
2.Eclipse JNoSQL通信层
Technically speaking, the communication layer consists of two modules: Diana API and a driver.
从技术上讲,通信层由两个模块组成。Diana API和一个驱动程序。
While the API defines an abstraction to NoSQL database types, the driver provides implementations for most known databases.
虽然API定义了对NoSQL数据库类型的抽象,但该驱动为大多数已知的数据库提供了实现。
We can compare this with the JDBC API and JDBC driver in relational databases.
我们可以将其与关系型数据库中的JDBC API和JDBC驱动进行比较。
2.1. Eclipse JNoSQL Diana API
2.1. Eclipse JNoSQL Diana API
Simply put, there are four basic types of NoSQL databases: Key-Value, Column, Document, and Graph.
简单地说,有四种基本类型的NoSQL数据库。键值型、列型、文档型和图型。
And the Eclipse JNoSQL Diana API defines three modules:
而Eclipse JNoSQL Diana API定义了三个模块。
- diana-key-value
- diana-column
- diana-document
The NoSQL graph type isn’t covered by the API, because it is already covered by Apache ThinkerPop.
该API没有涵盖NoSQL图类型,因为它已经被Apache ThinkerPop所涵盖。
The API is based on a core module, diana-core, and defines an abstraction to common concepts, such as Configuration, Factory, Manager, Entity, and Value.
该API基于一个核心模块diana-core,并定义了常见概念的抽象,如配置、工厂、经理、实体和价值。
To work with the API, we need to provide the dependency of the corresponding module to our NoSQL database type.
为了使用API,我们需要提供相应模块对我们的NoSQL数据库类型的依赖性。
Thus, for a document-oriented database, we’ll need the diana-document dependency:
因此,对于面向文档的数据库,我们需要diana-document依赖关系。
<dependency>
<groupId>org.jnosql.diana</groupId>
<artifactId>diana-document</artifactId>
<version>0.0.6</version>
</dependency>
Similarly, we should use the diana-key-value module if the working NoSQL database is key-value oriented:
同样地,如果工作中的NoSQL数据库是面向键值的,我们应该使用diana-key-value模块。
<dependency>
<groupId>org.jnosql.diana</groupId>
<artifactId>diana-key-value</artifactId>
<version>0.0.6</version>
</dependency>
And finally, the diana-column module if it’s a column-oriented:
最后是diana-column模块,如果它是一个面向列的模块。
<dependency>
<groupId>org.jnosql.diana</groupId>
<artifactId>diana-column</artifactId>
<version>0.0.6</version>
</dependency>
The most recent versions can be found on Maven Central.
最新的版本可以在Maven Central上找到。
2.2. Eclipse JNoSQL Diana Driver
2.2.Eclipse JNoSQL Diana驱动
The driver is a set of implementations of the API for the most common NoSQL databases.
该驱动程序是最常见的NoSQL数据库的API的一组实现。
There’s one implementation per NoSQL database. If the database is multi-model, the driver should implement all supported APIs.
每个NoSQL数据库有一个实现。如果数据库是多模型的,驱动程序应该实现所有支持的API。
For example, the couchbase-driver implements both diana-document and diana-key-value because Couchbase is both document and key-value oriented.
例如,couchbase-driver同时实现了diana-document和diana-key-value,因为Couchbase既面向文档又面向key-value。
Unlike with relational databases, where the driver is typically provided by the database vendor, here the driver is provided by Eclipse JNoSQL. In most cases, this driver is a wrapper around the official vendor library.
与关系型数据库不同的是,驱动通常由数据库供应商提供,而这里的驱动是由Eclipse JNoSQL提供的。在大多数情况下,该驱动程序是官方供应商库的一个包装。
To get started with the driver, we should include the API and the corresponding implementation for the chosen NoSQL database.
为了开始使用驱动程序,我们应该包括API和所选NoSQL数据库的相应实现。
For MongoDB, for example, we need to include the following dependencies:
以MongoDB为例,我们需要包括以下依赖项。
<dependency>
<groupId>org.jnosql.diana</groupId>
<artifactId>diana-document</artifactId>
<version>0.0.6</version>
</dependency>
<dependency>
<groupId>org.jnosql.diana</groupId>
<artifactId>mongodb-driver</artifactId>
<version>0.0.6</version>
</dependency>
The process behind working with the Driver is simple.
与司机合作的过程很简单。
First, we need a Configuration bean. By reading a configuration file from the classpath or hardcoding values, the Configuration is able to create a Factory. We then use it then to create a Manager.
首先,我们需要一个Configuration bean。通过从classpath读取配置文件或硬编码值,Configuration能够创建一个Factory.,然后我们用它来创建一个Manager.。
Finally, The Manager is responsible for pushing and retrieving the Entity to and from the NoSQL database.
最后,Manager负责向NoSQL数据库推送和检索Entity。
In the next subsections, we’ll explain this process for each NoSQL database type.
在接下来的小节中,我们将针对每种NoSQL数据库类型解释这一过程。
2.3. Working With a Document-Oriented Database
2.3.在面向文档的数据库中工作
In this example, we’ll be using an embedded MongoDB as it’s simple to get started with and doesn’t require installation. It’s document-oriented and the following instructions are applicable to any other document-oriented NoSQL database.
在这个例子中,我们将使用嵌入式MongoDB,因为它很容易上手,不需要安装。它是面向文档的,以下说明适用于任何其他面向文档的NoSQL数据库。
At the very beginning, we should provide all necessary settings needed by the application to properly interact with the database. In its most elementary form, we should provide the host and the port of a running instance of the MongoDB.
在一开始,我们应该提供应用程序所需的所有必要设置,以便与数据库正确互动。在其最基本的形式中,我们应该提供MongoDB的运行实例的host和port。
We can provide these settings either in the mongodb-driver.properties located on the classpath:
我们可以在位于classpath的mongodb-driver.properties中提供这些设置。
#Define Host and Port
mongodb-server-host-1=localhost:27017
Or as a hardcoded values:
或者作为一个硬编码值。
Map<String, Object> map = new HashMap<>();
map.put("mongodb-server-host-1", "localhost:27017");
Next, we create the Configuration bean for the document type:
接下来,我们为文档类型创建Configuration bean。
DocumentConfiguration configuration = new MongoDBDocumentConfiguration();
From this Configuration bean, we are able to create a ManagerFactory:
从这个Configuration bean中,我们能够创建一个ManagerFactory。
DocumentCollectionManagerFactory managerFactory = configuration.get();
Implicitly, the get() method of the Configuration bean uses settings from the properties file. We can also obtain this factory from hardcoded values:
隐含地,Configuration Bean的get()方法使用来自属性文件的设置。我们也可以从硬编码值中获得这个工厂。
DocumentCollectionManagerFactory managerFactory
= configuration.get(Settings.of(map));
The ManagerFactory has a simple method get(), that takes the database name as a parameter, and creates the Manager:
ManagerFactory有一个简单的方法get(),将数据库名称作为一个参数,并创建Manager。
DocumentCollectionManager manager = managerFactory.get("my-db");
And finally, we’re ready. The Manager provides all the necessary methods to interact with the underlying NoSQL database through the DocumentEntity.
最后,我们准备好了。Manager 提供了所有必要的方法,以便通过DocumentEntity.与底层NoSQL数据库交互。
So, we could, for example, insert a document:
因此,我们可以,比如说,插入一个文件。
DocumentEntity documentEntity = DocumentEntity.of("books");
documentEntity.add(Document.of("_id", "100"));
documentEntity.add(Document.of("name", "JNoSQL in Action"));
documentEntity.add(Document.of("pages", "620"));
DocumentEntity saved = manager.insert(documentEntity);
We could also search for documents:
我们还可以搜索文件。
DocumentQuery query = select().from("books").where("_id").eq(100).build();
List<DocumentEntity> entities = manager.select(query);
And in a similar manner, we could update an existing document:
而以类似的方式,我们可以更新一个现有的文件。
saved.add(Document.of("author", "baeldung"));
DocumentEntity updated = manager.update(saved);
And finally, we can delete a stored document:
最后,我们可以删除一个存储的文件。
DocumentDeleteQuery deleteQuery = delete().from("books").where("_id").eq("100").build();
manager.delete(deleteQuery);
To run the sample, we just need to access the jnosql-diana module and run the DocumentApp application.
要运行这个样本,我们只需要访问jnosql-diana模块并运行DocumentApp应用程序。
We should see the output in the console:
我们应该在控制台看到输出。
DefaultDocumentEntity{documents={pages=620, name=JNoSQL in Action, _id=100}, name='books'}
DefaultDocumentEntity{documents={pages=620, author=baeldung, name=JNoSQL in Action, _id=100}, name='books'}
[]
2.4. Working With a Column-Oriented Database
2.4.在面向列的数据库中工作
For the purpose of this section, we’ll use an embedded version of the Cassandra database, so no installation is needed.
在本节中,我们将使用Cassandra数据库的嵌入式版本,所以不需要安装。
The process for working with a Column-oriented database is very similar. First of all, we add the Cassandra driver and the column API to the pom:
与面向列的数据库的工作过程非常相似。首先,我们将Cassandra驱动和列API添加到pom中。
<dependency>
<groupId>org.jnosql.diana</groupId>
<artifactId>diana-column</artifactId>
<version>0.0.6</version>
</dependency>
<dependency>
<groupId>org.jnosql.diana</groupId>
<artifactId>cassandra-driver</artifactId>
<version>0.0.6</version>
</dependency>
Next, we need the configuration settings specified in the configuration file, diana-cassandra.properties, on the classpath. Alternatively, we could also use hardcoded configuration values.
接下来,我们需要在classpath上的配置文件diana-cassandra.properties中指定配置设置。另外,我们也可以使用硬编码的配置值。
Then, with a similar approach, we’ll create a ColumnFamilyManager and start manipulating the ColumnEntity:
然后,用类似的方法,我们将创建一个ColumnFamilyManager并开始操作ColumnEntity:。
ColumnConfiguration configuration = new CassandraConfiguration();
ColumnFamilyManagerFactory managerFactory = configuration.get();
ColumnFamilyManager entityManager = managerFactory.get("my-keySpace");
So to create a new entity, let’s invoke the insert() method:
所以为了创建一个新的实体,让我们调用insert()方法。
ColumnEntity columnEntity = ColumnEntity.of("books");
Column key = Columns.of("id", 10L);
Column name = Columns.of("name", "JNoSQL in Action");
columnEntity.add(key);
columnEntity.add(name);
ColumnEntity saved = entityManager.insert(columnEntity);
To run the sample and see the output in the console, run the ColumnFamilyApp application.
要运行样本并在控制台看到输出,请运行ColumnFamilyApp应用程序。
2.5. Working With a Key-Value Oriented Database
2.5.在面向键值的数据库中工作
In this section, we’ll use the Hazelcast. Hazelcast is a key-value oriented NoSQL database. For more information on the Hazelcast database, you can check this link.
在本节中,我们将使用Hazelcast。Hazelcast是一个面向键值的NoSQL数据库。关于Hazelcast数据库的更多信息,你可以查看这个链接。
The process for working with the key-value oriented type is also similar. We start by adding these dependencies to the pom:
处理面向键值的类型的过程也是类似的。我们首先将这些依赖关系添加到pom中。
<dependency>
<groupId>org.jnosql.diana</groupId>
<artifactId>diana-key-value</artifactId>
<version>0.0.6</version>
</dependency>
<dependency>
<groupId>org.jnosql.diana</groupId>
<artifactId>hazelcast-driver</artifactId>
<version>0.0.6</version>
</dependency>
Then we need to provide the configuration settings. Next, we can obtain a BucketManager and then manipulate the KeyValueEntity:
然后我们需要提供配置设置。接下来,我们可以获得一个BucketManager,然后操作KeyValueEntity:。
KeyValueConfiguration configuration = new HazelcastKeyValueConfiguration();
BucketManagerFactory managerFactory = configuration.get();
BucketManager entityManager = managerFactory.getBucketManager("books");
Let’s say we want to save the following Book model:
假设我们想保存以下Book模型。
public class Book implements Serializable {
private String isbn;
private String name;
private String author;
private int pages;
// standard constructor
// standard getters and setters
}
So we create a Book instance and then we save it by invoking the put() method;
所以我们创建一个Book实例,然后通过调用put()方法来保存它。
Book book = new Book(
"12345", "JNoSQL in Action",
"baeldung", 420);
KeyValueEntity keyValueEntity = KeyValueEntity.of(
book.getIsbn(), book);
entityManager.put(keyValueEntity);
Then to retrieve the saved Book instance:
然后检索保存的Book实例。
Optional<Value> optionalValue = manager.get("12345");
Value value = optionalValue.get(); // or any other adequate Optional handling
Book savedBook = value.get(Book.class);
To run the sample and see the output in the console, run the KeyValueApp application.
要运行样本并在控制台看到输出,请运行KeyValueApp应用程序。
3. Eclipse JNoSQL Mapping Layer
3.Eclipse JNoSQL映射层
The mapping layer, Artemis API, is a set of APIs that help map java annotated Objects to NoSQL databases. It’s based on the Diana API and CDI (Context and Dependency Injection).
映射层,即Artemis API,是一套帮助将java注释的对象映射到NoSQL数据库的API。它是基于Diana API和CDI(上下文和依赖注入)的。
We can consider this API as JPA or ORM like for the NoSQL world. This layer also provides an API for each NoSQL type and one core API for common features.
我们可以把这个API看作是类似于NoSQL世界的JPA或ORM。该层还为每种NoSQL类型提供了一个API,并为通用功能提供一个核心API。
In this section, we’re going to work with the MongoDB document-oriented database.
在本节中,我们将与MongoDB面向文档的数据库一起工作。
3.1. Required Dependencies
3.1.必要的依赖性
To enable Artemis in the application, we need to add the artemis-configuration dependency. Since MongoDB is document-oriented, the dependency artemis-document is also needed.
为了在应用程序中启用Artemis,我们需要添加artemis-configuration依赖项。由于MongoDB是面向文档的,因此还需要依赖artemis-document。
For other types of NoSQL databases, we would use artemis-column, artemis-key-value and artemis-graph.
对于其他类型的NoSQL数据库,我们会使用artemis-column、artemis-key-value和artemis-graph。
The Diana driver for MongoDB is also needed:
还需要MongoDB的Diana驱动。
<dependency>
<groupId>org.jnosql.artemis</groupId>
<artifactId>artemis-configuration</artifactId>
<version>0.0.6</version>
</dependency>
<dependency>
<groupId>org.jnosql.artemis</groupId>
<artifactId>artemis-document</artifactId>
<version>0.0.6</version>
</dependency>
<dependency>
<groupId>org.jnosql.diana</groupId>
<artifactId>mongodb-driver</artifactId>
<version>0.0.6</version>
</dependency>
Artemis is based on CDI, so we need also to provide this Maven dependency:
Artemis是基于CDI的,所以我们也需要提供这个Maven依赖。
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
3.2. The Document Configuration File
3.2.文件配置文件
A configuration is a set of properties for a given database that let us provides setting outside the code. By default, we need to supply the jnosql.json file under the META-INF resource.
配置是一组给定数据库的属性,让我们在代码之外提供设置。默认情况下,我们需要在META-INF资源下提供jnosql.json文件。
This is an example of the configuration file:
这是一个配置文件的例子。
[
{
"description": "The mongodb document configuration",
"name": "document",
"provider": "org.jnosql.diana.mongodb.document.MongoDBDocumentConfiguration",
"settings": {
"mongodb-server-host-1":"localhost:27019"
}
}
]
We will need to specify the configuration name above by setting the name attribute in our ConfigurationUnit. If the configuration is in a different file, it can be specified by using the fileName attribute.
我们将需要通过在我们的ConfigurationUnit中设置name属性来指定上面的配置名称。如果配置在一个不同的文件中,可以通过使用fileName属性来指定它。
Given this configuration, we create a factory:
鉴于这种配置,我们创建一个工厂。
@Inject
@ConfigurationUnit(name = "document")
private DocumentCollectionManagerFactory<MongoDBDocumentCollectionManager> managerFactory;
And from this factory, we can create a DocumentCollectionManager:
而从这个工厂,我们可以创建一个DocumentCollectionManager。
@Produces
public MongoDBDocumentCollectionManager getEntityManager() {
return managerFactory.get("todos");
}
The DocumentCollectionManager is a CDI enabled bean and it is used in both the Template and Repository.
DocumentCollectionManager是一个支持CDI的bean,它在Template和Repository.中都被使用。
3.3. Mapping
3.3.绘图
The mapping is an annotation-driven process by which the Entity model is converted to the Diana EntityValue.
映射是一个注释驱动的过程,通过这个过程,Entity模型被转换为戴安娜EntityValue.。
Let’s start by defining a Todo model:
让我们从定义一个Todo模型开始。
@Entity
public class Todo implements Serializable {
@Id("id")
public long id;
@Column
public String name;
@Column
public String description;
// standard constructor
// standard getters and setters
}
As shown above, we have the basic mapping annotations: @Entity, @Id, and @Column.
如上所示,我们有基本的映射注解。@Entity, @Id, 和 @Column.。
Now to manipulate this model, we need either a Template class or a Repository interface.
现在要操作这个模型,我们需要一个Template类或Repository接口。
3.4. Working With the Template
3.4.利用模板工作
The template is the bridge between the entity model and the Diana API. For a document-oriented database, we start by injecting the DocumentTemplate bean:
模板是实体模型和Diana API之间的桥梁。对于面向文档的数据库,我们首先要注入DocumentTemplate Bean。
@Inject
DocumentTemplate documentTemplate;
And then, we can manipulate the Todo Entity. For example, we can create a Todo:
然后,我们可以操作Todo实体。例如,我们可以创建一个Todo。
public Todo add(Todo todo) {
return documentTemplate.insert(todo);
}
Or we can retrieve a Todo by id:
或者我们可以通过id来检索一个Todo。
public Todo get(String id) {
Optional<Todo> todo = documentTemplate
.find(Todo.class, id);
return todo.get(); // or any other proper Optional handling
}
To select all entities, we build a DocumentQuery and then we invoke the select() method:
为了选择所有的实体,我们建立一个DocumentQuery,然后我们调用select()方法。
public List<Todo> getAll() {
DocumentQuery query = select().from("Todo").build();
return documentTemplate.select(query);
}
And finally we can delete a Todo entity by id:
最后,我们可以通过id删除一个Todo实体。
public void delete(String id) {
documentTemplate.delete(Todo.class, id);
}
3.5. Working With the Repository
3.5.与存储库一起工作
In addition to the Template class, we can also manage entities through the Repository interface which has methods for creating, updating, deleting and retrieving information.
除了Template类,我们还可以通过Repository接口来管理实体,该接口有创建、更新、删除和检索信息的方法。
To use the Repository interface, we just provide a subinterface of the Repository:
为了使用Repository接口,我们只需提供Repository的一个子接口:。
public interface TodoRepository extends Repository<Todo, String> {
List<Todo> findByName(String name);
List<Todo> findAll();
}
By the following method and parameter naming conventions, an implementation of this interface is provided at runtime as a CDI bean.
通过以下方法和参数的命名约定,这个接口的实现在运行时作为CDI bean提供。
In this example, all Todo entities with a matching name are retrieved by the findByName() method.
在这个例子中,所有具有匹配name的Todo实体都被findByName()方法所检索。
We can now use it:
我们现在可以使用它。
@Inject
TodoRepository todoRepository;
The Database qualifier lets us work with more than one NoSQL database in the same application. It comes with two attributes, the type and the provider.
Database限定符让我们可以在同一个应用程序中使用一个以上的NoSQL数据库。它有两个属性,类型和提供者。
If the database is multi-model, then we need to specify which model we are working with:
如果数据库是多模型的,那么我们需要指定我们正在处理的模型。
@Inject
@Database(value = DatabaseType.DOCUMENT)
TodoRepository todoRepository;
Additionally, if we have more than one database of the same model, we need to specify the provider:
此外,如果我们有一个以上的相同模型的数据库,我们需要指定提供者。
@Inject
@Database(value = DatabaseType.DOCUMENT, provider="org.jnosql.diana.mongodb.document.MongoDBDocumentConfiguration")
TodoRepository todoRepository;
To run the sample, just access the jnosql-artemis module and invoke this command:
要运行这个样本,只需访问jnosql-artemis模块并调用这个命令。
mvn package liberty:run
This command builds, deploy and start the Open Liberty server thanks to the liberty-maven-plugin.
该命令构建、部署和启动Open Liberty服务器,这得益于liberty-maven-plugin。
3.6. Testing the Application
3.6.测试应用程序
As the application exposes a REST endpoint, we can use any REST client for our tests. Here we used the curl tool.
由于该应用程序暴露了一个REST端点,我们可以使用任何REST客户端进行测试。这里我们使用了curl工具。
So to save a Todo class:
所以要保存一个Todo类。
curl -d '{"id":"120", "name":"task120", "description":"Description 120"}' -H "Content-Type: application/json" -X POST http://localhost:9080/jnosql-artemis/todos
and to get all Todo:
并获得所有Todo。
curl -H "Accept: application/json" -X GET http://localhost:9080/jnosql-artemis/todos
Or to get just one Todo:
或者只得到一个Todo。
curl -H "Accept: application/json" -X GET http://localhost:9080/jnosql-artemis/todos/120
4. Conclusion
4.结论
In this tutorial, we have explored how JNoSQL is able to abstract the interaction with a NoSQL database.
在本教程中,我们已经探讨了JNoSQL如何能够抽象出与NoSQL数据库的交互。
First, we have used JNoSQL Diana API to interact with the database with low-level code. Then, we used the JNoSQL Artemis API to work with friendly Java annotated Models.
首先,我们使用JNoSQL Diana API与数据库进行了低级别的代码交互。然后,我们使用JNoSQL Artemis API来与友好的Java注释模型进行工作。
As usual, we can find the code used in this article over on Github.
像往常一样,我们可以在Github上找到本文中使用的代码over。