1. 概述
在系列文章的前一篇中,我们展示了如何将 Java 对象持久化到不同的数据存储。更多细节请参考 Java 数据对象指南。
JDO 支持多种查询语言,为开发者提供灵活性,使其能使用最熟悉的查询语言。
2. JDO 查询语言
JDO 支持以下查询语言:
- JDOQL – 使用 Java 语法的查询语言
- Typed JDOQL – 遵循 JDOQL 语法但提供 API 简化查询使用
- SQL – 仅用于关系型数据库
- JPQL – 由 Datanucleus 提供,但非 JDO 规范的一部分
3. 查询 API
3.1 创建查询
创建查询时,需要指定语言和查询字符串:
Query query = pm.newQuery(
"javax.jdo.query.SQL",
"select * from product_item where price < 10");
若未指定语言,默认使用 JDOQL:
Query query = pm.newQuery(
"SELECT FROM com.baeldung.jdo.query.ProductItem WHERE price < 10");
3.2 创建命名查询
可定义查询并通过名称引用。首先创建 ProductItem
类:
@PersistenceCapable
public class ProductItem {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.INCREMENT)
int id;
String name;
String status;
String description;
double price;
//标准 getter/setter/构造方法
}
然后在 META-INF/package.jdo
中添加类配置定义命名查询:
<jdo>
<package name="com.baeldung.jdo.query">
<class name="ProductItem" detachable="true" table="product_item">
<query name="PriceBelow10" language="javax.jdo.query.SQL">
<![CDATA[SELECT * FROM PRODUCT_ITEM WHERE PRICE < 10]]>
</query>
</class>
</package>
</jdo>
定义了名为 "PriceBelow10" 的查询。代码中使用方式:
Query<ProductItem> query = pm.newNamedQuery(
ProductItem.class, "PriceBelow10");
List<ProductItem> items = query.executeList();
3.3 关闭查询
为节省资源,可关闭查询:
query.close();
或通过传递结果集关闭特定结果:
query.close(ResultSet);
3.4 编译查询
调用 compile()
方法验证查询有效性:
query.compile();
若查询无效,将抛出 JDOException
。
4. JDOQL
JDOQL 是基于对象的查询语言,旨在提供 SQL 的能力,同时保留应用模型中的 Java 对象关系。
JDOQL 查询可定义为单字符串形式。深入前先了解基础概念:
4.1 候选类
候选类必须是可持久化类。使用完整类名而非 SQL 中的表名:
Query query = pm.newQuery("SELECT FROM com.baeldung.jdo.query.ProductItem");
List<ProductItem> r = query.executeList();
示例中 com.baeldung.jdo.query.ProductItem
即为候选类。
4.2 过滤器
过滤器可用 Java 编写,但必须求值为布尔值:
Query query = pm.newQuery("SELECT FROM com.baeldung.jdo.query.ProductItem");
query.setFilter("status == 'SoldOut'");
List<ProductItem> result = query.executeList();
4.3 方法
JDOQL 不支持所有 Java 方法,但支持多种可在查询中调用的方法:
query.setFilter("this.name.startsWith('supported')");
支持方法完整列表见官方文档。
4.4 参数
可通过参数传递值。可显式或隐式定义参数。
显式定义参数:
Query query = pm.newQuery(
"SELECT FROM com.baeldung.jdo.query.ProductItem "
+ "WHERE price < threshold PARAMETERS double threshold");
List<ProductItem> result = (List<ProductItem>) query.execute(10);
或使用 setParameters
方法:
Query query = pm.newQuery(
"SELECT FROM com.baeldung.jdo.query.ProductItem "
+ "WHERE price < :threshold");
query.setParameters("double threshold");
List<ProductItem> result = (List<ProductItem>) query.execute(10);
隐式定义(不指定参数类型):
Query query = pm.newQuery(
"SELECT FROM com.baeldung.jdo.query.ProductItem "
+ "WHERE price < :threshold");
List<ProductItem> result = (List<ProductItem>) query.execute(10);
5. 类型化 JDOQL
使用 JDOQLTypedQueryAPI 需准备环境。
5.1 Maven 配置
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-jdo-query</artifactId>
<version>6.0.1</version>
</dependency>
最新版本见 Maven 中央仓库。
5.2 启用注解处理
Eclipse 配置步骤:
- 进入 Java Compiler,确保编译器级别 ≥ 1.8
- 进入 Java Compiler → Annotation Processing,启用项目特定设置并激活注解处理
- 进入 Java Compiler → Annotation Processing → Factory Path,启用项目特定设置,添加以下 JAR:
javax.jdo.jar
、datanucleus-jdo-query.jar
配置后,编译可持久化类时,datanucleus-jdo-query.jar
中的注解处理器会为每个 @PersistenceCapable
注解类生成查询类。示例中生成 QProductItem
类(类名前缀 Q)。
5.3 创建类型化 JDOQL 查询
JDOQLTypedQuery<ProductItem> tq = pm.newJDOQLTypedQuery(ProductItem.class);
QProductItem cand = QProductItem.candidate();
tq = tq.filter(cand.price.lt(10).and(cand.name.startsWith("pro")));
List<ProductItem> results = tq.executeList();
利用生成的查询类访问候选字段并调用其 Java 方法。
6. SQL
使用关系型数据库时,JDO 支持 SQL 查询:
Query query = pm.newQuery("javax.jdo.query.SQL","select * from "
+ "product_item where price < ? and status = ?");
query.setClass(ProductItem.class);
query.setParameters(10,"InStock");
List<ProductItem> results = query.executeList();
通过 setClass()
指定返回 ProductItem
对象,否则返回 Object
类型。
7. JPQL
JDO DataNucleus 提供 JPQL 支持:
Query query = pm.newQuery("JPQL","select i from "
+ "com.baeldung.jdo.query.ProductItem i where i.price < 10"
+ " and i.status = 'InStock'");
List<ProductItem> results = (List<ProductItem>) query.execute();
实体名为完整类名(因 JDO 无 JPA 式实体名元数据)。定义别名 i
后可用其引用 ProductItem
。JPQL 语法细节见官方文档。
8. 总结
本文展示了 JDO 支持的多种查询语言,包括: ✅ 命名查询的复用方式 ✅ JDOQL 核心概念(候选类/过滤器/方法/参数) ✅ 类型化 JDOQL 的配置与使用 ✅ SQL 和 JPQL 在 JDO 中的集成
合理选择查询语言可显著提升开发效率,避免踩坑。