1. 概述

Eclipse JNoSQL 是一组用于简化 Java 应用与 NoSQL 数据库交互的 API 和实现

本文将带你从零开始配置和使用 JNoSQL,涵盖其两大核心模块:通信层(Communication Layer)映射层(Mapping Layer)。前者适合需要精细控制数据库操作的场景,后者则更贴近现代开发习惯,支持注解驱动的 ORM 风格操作。

✅ 适合有经验的开发者快速上手
⚠️ 不适合想了解 NoSQL 基础概念的初学者


2. Eclipse JNoSQL 通信层

通信层是 JNoSQL 的底层基础,由两部分组成:

  • Diana API:定义了对 NoSQL 数据库类型的抽象
  • Driver(驱动):为具体数据库提供实现

你可以把它类比为关系型数据库中的 JDBC API 和 JDBC Driver。

2.1. Diana API 模块

NoSQL 常见分为四类:Key-Value、Column、Document 和 Graph。Diana API 覆盖了前三类,分别对应三个模块:

  1. diana-key-value —— 键值型
  2. diana-column —— 列式(如 Cassandra)
  3. diana-document —— 文档型(如 MongoDB)

⚠️ Graph 图数据库未被覆盖,因其已有成熟的 Apache TinkerPop 生态。

所有模块基于 diana-core,抽象出通用概念:ConfigurationFactoryManagerEntityValue

使用时需引入对应类型的依赖。例如,操作 MongoDB 需引入文档模块:

<dependency>
    <groupId>org.jnosql.diana</groupId>
    <artifactId>diana-document</artifactId>
    <version>0.0.6</version>
</dependency>

键值型数据库(如 Redis、Hazelcast):

<dependency>
    <groupId>org.jnosql.diana</groupId>
    <artifactId>diana-key-value</artifactId>
    <version>0.0.6</version>
</dependency>

列式数据库(如 Cassandra):

<dependency>
    <groupId>org.jnosql.diana</groupId>
    <artifactId>diana-column</artifactId>
    <version>0.0.6</version>
</dependency>

📌 最新版可在 Maven Central 查询。


2.2. Diana Driver 驱动实现

Driver 是 Diana API 的具体实现,由 Eclipse JNoSQL 团队提供,通常是对官方客户端库的封装。

与传统 JDBC 不同,这里 Driver 并非由数据库厂商提供,而是统一由 JNoSQL 维护。若数据库支持多模型(如 Couchbase 同时支持文档和键值),则其 Driver 会实现多个 Diana 模块。

以 MongoDB 为例,需同时引入 API 和 Driver:

<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>

工作流程非常清晰:

  1. 创建 Configuration 实例
  2. 通过 Configuration.get() 获取 ManagerFactory
  3. 使用 ManagerFactory.get(dbName) 获取 Manager
  4. 通过 Manager 操作 Entity

下面以不同类型数据库演示具体用法。


2.3. 操作文档型数据库(以 MongoDB 为例)

使用嵌入式 MongoDB,无需安装,适合本地测试。

配置方式

可通过配置文件 mongodb-driver.properties(位于 classpath)设置:

#Define Host and Port
mongodb-server-host-1=localhost:27017

或代码硬编码:

Map<String, Object> map = new HashMap<>();
map.put("mongodb-server-host-1", "localhost:27017");

初始化 Manager

DocumentConfiguration configuration = new MongoDBDocumentConfiguration();
DocumentCollectionManagerFactory managerFactory = configuration.get();
// 或使用硬编码配置
// DocumentCollectionManagerFactory managerFactory = configuration.get(Settings.of(map));

DocumentCollectionManager manager = managerFactory.get("my-db");

CRUD 操作

插入文档:

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);

查询:

DocumentQuery query = select().from("books").where("_id").eq(100).build();
List<DocumentEntity> entities = manager.select(query);

更新:

saved.add(Document.of("author", "baeldung"));
DocumentEntity updated = manager.update(saved);

删除:

DocumentDeleteQuery deleteQuery = delete().from("books").where("_id").eq("100").build();
manager.delete(deleteQuery);

运行 DocumentApp 可看到控制台输出:

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'}
[]

✅ 简单粗暴,适合需要直接操作底层 Entity 的场景。


2.4. 操作列式数据库(以 Cassandra 为例)

使用嵌入式 Cassandra,免安装。

引入依赖:

<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>

配置文件:diana-cassandra.properties

初始化:

ColumnConfiguration configuration = new CassandraConfiguration();
ColumnFamilyManagerFactory managerFactory = configuration.get();
ColumnFamilyManager entityManager = managerFactory.get("my-keySpace");

插入数据:

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);

运行 ColumnFamilyApp 查看结果。


2.5. 操作键值型数据库(以 Hazelcast 为例)

Hazelcast 是典型的键值型 NoSQL 数据库。

依赖:

<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>

初始化:

KeyValueConfiguration configuration = new HazelcastKeyValueConfiguration();
BucketManagerFactory managerFactory = configuration.get();
BucketManager entityManager = managerFactory.getBucketManager("books");

定义实体类:

public class Book implements Serializable {

    private String isbn;
    private String name;
    private String author;
    private int pages;

    // standard constructor
    // standard getters and setters
}

保存:

Book book = new Book(
  "12345", "JNoSQL in Action", 
  "baeldung", 420);
KeyValueEntity keyValueEntity = KeyValueEntity.of(
  book.getIsbn(), book);
entityManager.put(keyValueEntity);

读取:

Optional<Value> optionalValue = manager.get("12345");
Value value = optionalValue.get(); // 注意处理 Optional
Book savedBook = value.get(Book.class);

运行 KeyValueApp 即可验证。


3. Eclipse JNoSQL 映射层(Artemis API)

如果你厌倦了手动构造 DocumentEntity,Artemis 就是为你准备的。

Artemis 是 JNoSQL 的映射层,类似于 JPA 之于 NoSQL。它基于 Diana API 和 CDI(Context and Dependency Injection),支持注解驱动的实体映射。

本节以 MongoDB 文档数据库为例。

3.1. 所需依赖

<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 依赖 CDI,需引入:

<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-web-api</artifactId>
    <version>8.0</version>
    <scope>provided</scope>
</dependency>

3.2. 配置文件 jnosql.json

推荐将配置外置。默认从 META-INF/jnosql.json 读取:

[
    {
        "description": "The mongodb document configuration",
        "name": "document",
        "provider": "org.jnosql.diana.mongodb.document.MongoDBDocumentConfiguration",
        "settings": {
            "mongodb-server-host-1":"localhost:27019"
        }
    }
]

在代码中通过 @ConfigurationUnit 注入:

@Inject
@ConfigurationUnit(name = "document")
private DocumentCollectionManagerFactory<MongoDBDocumentCollectionManager> managerFactory;

生成 Manager

@Produces
public MongoDBDocumentCollectionManager getEntityManager() {
    return managerFactory.get("todos");
}

Manager 会被用于 TemplateRepository


3.3. 实体映射

使用注解定义实体模型:

@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
}

核心注解说明:

  • @Entity:标记为持久化实体
  • @Id:指定主键字段(可自定义列名)
  • @Column:普通字段映射

3.4. 使用 Template

Template 是实体与 Diana API 之间的桥梁。

注入:

@Inject
DocumentTemplate documentTemplate;

常用操作:

新增:

public Todo add(Todo todo) {
    return documentTemplate.insert(todo);
}

根据 ID 查询:

public Todo get(String id) {
    Optional<Todo> todo = documentTemplate.find(Todo.class, id);
    return todo.get(); // 注意 Optional 处理
}

查询全部:

public List<Todo> getAll() {
    DocumentQuery query = select().from("Todo").build();
    return documentTemplate.select(query);
}

删除:

public void delete(String id) {
    documentTemplate.delete(Todo.class, id);
}

3.5. 使用 Repository

更高级的抽象,支持接口定义 + 方法命名自动实现。

定义接口:

public interface TodoRepository extends Repository<Todo, String> {
    List<Todo> findByName(String name);
    List<Todo> findAll();
}

findByName 自动解析为按 name 字段查询
findAll 返回所有记录

注入使用:

@Inject
TodoRepository todoRepository;

支持多数据库场景:

指定数据库类型:

@Inject
@Database(value = DatabaseType.DOCUMENT)
TodoRepository todoRepository;

指定具体 Provider(应对多个同类型数据库):

@Inject
@Database(value = DatabaseType.DOCUMENT, provider="org.jnosql.diana.mongodb.document.MongoDBDocumentConfiguration")
TodoRepository todoRepository;

启动应用:

mvn package liberty:run

该命令通过 liberty-maven-plugin 构建并启动 Open Liberty 服务器。


3.6. 接口测试

应用暴露了 REST 接口,可用 curl 测试:

新增 Todo:

curl -d '{"id":"120", "name":"task120", "description":"Description 120"}' -H "Content-Type: application/json" -X POST http://localhost:9080/jnosql-artemis/todos

查询全部:

curl -H "Accept: application/json" -X GET http://localhost:9080/jnosql-artemis/todos

查询单个:

curl -H "Accept: application/json" -X GET http://localhost:9080/jnosql-artemis/todos/120

4. 总结

JNoSQL 提供了两套互补的 NoSQL 操作方案:

  • 通信层(Diana):适合需要精细控制、性能敏感的场景,直接操作 Entity
  • 映射层(Artemis):适合快速开发,支持注解和 Repository 模式,开发体验接近 JPA

两者底层统一,可灵活切换。对于新项目,推荐从 Artemis 入手,必要时再深入 Diana 层进行优化。

代码已上传至 GitHub:https://github.com/eugenp/tutorials/tree/master/persistence-modules/jnosql


原始标题:A Guide to Eclipse JNoSQL