1. 概述

Java数据对象(JDO)是一种API,用于将面向对象的数据持久化到任何数据库,并提供使用Java语法的用户友好查询语言。

本文将演示如何使用JDO API将对象持久化到数据库中,涵盖从基础配置到高级查询的全流程操作。

2. Maven依赖与配置

我们将使用DataNucleus JDO API,它完全支持JDO 3.2规范且保持最新更新。

pom.xml中添加以下依赖:

<dependency>
    <groupId>org.datanucleus</groupId>
    <artifactId>javax.jdo</artifactId>
    <version>3.2.1</version>
</dependency>
<dependency>
    <groupId>org.datanucleus</groupId>
    <artifactId>datanucleus-core</artifactId>
    <version>6.0.6</version>
</dependency>
<dependency>
    <groupId>org.datanucleus</groupId>
    <artifactId>datanucleus-api-jdo</artifactId>
    <version>6.0.1</version>
</dependency>
<dependency>
    <groupId>org.datanucleus</groupId>
    <artifactId>datanucleus-rdbms</artifactId>
    <version>6.0.6</version>
</dependency>

最新版本可在此获取: javax.jdo, datanucleus-core, datanucleus-api-jdo, datanucleus-rdbms

3. 数据模型

在持久化数据前,需要创建JDO可识别的实体类。使用@PersistenceCapable注解标记持久化类:

@PersistenceCapable
public class Product {
 
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.INCREMENT)
    long id;
 
    String name;
    Double price = 0.0;

    // 标准构造器、getter和setter
}

关键点说明:

  • @PrimaryKey标识主键字段
  • IdGeneratorStrategy.INCREMENT设置自增策略
  • ⚠️ 创建类后必须运行增强器生成字节码

执行Maven命令进行增强:

mvn datanucleus:enhance

踩坑提示:跳过此步骤会导致编译错误提示"类未增强"

建议配置Maven插件自动执行增强:

<plugin>
    <groupId>org.datanucleus</groupId>
    <artifactId>datanucleus-maven-plugin</artifactId>
    <version>6.0.0-release</version>
    <configuration>
        <api>JDO</api>
        <props>${basedir}/datanucleus.properties</props>
        <log4jConfiguration>${basedir}/log4j.properties</log4jConfiguration>
        <verbose>true</verbose>
    </configuration>
    <executions>
        <execution>
            <phase>process-classes</phase>
            <goals>
                <goal>enhance</goal>
            </goals>
        </execution>
    </executions>
</plugin>

最新版本:datanucleus-maven-plugin

4. 持久化对象

通过JDO工厂获取数据库连接和事务管理器:

PersistenceManagerFactory pmf = new JDOPersistenceManagerFactory(pumd, null);
PersistenceManager pm = pmf.getPersistenceManager();

事务管理用于错误回滚:

Transaction tx = pm.currentTransaction();

try/catch块中执行持久化操作:

Product product = new Product("Tablet", 80.0);
pm.makePersistent(product);

finally块中处理异常情况:

finally {
    if (tx.isActive()) {
        tx.rollback();
    }
    pm.close();
}

创建运行时persistence-unit配置连接参数:

PersistenceUnitMetaData pumd = new PersistenceUnitMetaData(
  "dynamic-unit", "RESOURCE_LOCAL", null);
pumd.addClassName("com.baeldung.jdo.Product");
pumd.setExcludeUnlistedClasses();
pumd.addProperty("javax.jdo.option.ConnectionDriverName", "org.h2.Driver");
pumd
  .addProperty("javax.jdo.option.ConnectionURL", "jdbc:h2:mem:mypersistence");
pumd.addProperty("javax.jdo.option.ConnectionUserName", "sa");
pumd.addProperty("javax.jdo.option.ConnectionPassword", "");
pumd.addProperty("datanucleus.autoCreateSchema", "true");

5. 读取对象

在事务块中创建查询,将结果存储到Java集合:

Query q = pm.newQuery(
  "SELECT FROM " + Product.class.getName() + " WHERE price < 1");
List<Product> products = (List<Product>) q.execute();
Iterator<Product> iter = products.iterator();
while (iter.hasNext()) {
    Product p = iter.next();
    // 处理产品信息
}

6. 更新对象

更新流程:查询对象 → 修改属性 → 提交事务

Query query = pm.newQuery(Product.class, "name == \"Phone\"");
Collection result = (Collection) query.execute();
Product product = (Product) result.iterator().next();
product.setName("Android Phone");

7. 删除对象

删除流程:查询对象 → 调用删除方法 → 提交事务

Query query = pm.newQuery(Product.class, "name == \"Android Phone\"");
Collection result = (Collection) query.execute();
Product product = (Product) result.iterator().next();
pm.deletePersistent(product);

8. XML数据存储

使用XML插件可将数据持久化到XML文件。配置连接URL指定XML文件路径:

pumdXML.addProperty("javax.jdo.option.ConnectionURL", "xml:file:myPersistence.xml");

⚠️ XML存储不支持自增主键,需调整实体类:

@PersistenceCapable()
public class ProductXML {

    @XmlAttribute
    private long productNumber = 0;
    @PrimaryKey
    private String name = null;
    private Double price = 0.0;
 
    // 标准getter和setter
}

@XmlAttribute注解使字段作为XML元素的属性出现。

持久化示例:

ProductXML productXML = new ProductXML(0,"Tablet", 80.0);
pm.makePersistent(productXML);

生成的XML文件:

<productXML productNumber="0">
    <name>Tablet</name>
    <price>80.0</price>
</productXML>

8.1. 从XML存储恢复对象

通过查询恢复对象:

Query q = pm.newQuery("SELECT FROM " + ProductXML.class.getName());
List<ProductXML> products = (List<ProductXML>) q.execute();

使用迭代器遍历每个对象。

9. JDO查询

JDOQL是基于对象的查询语言,使用Java对象执行查询。

9.1. 声明式JDOQL

声明参数确保类型安全:

Query qDJDOQL = pm.newQuery(Product.class);
qDJDOQL.setFilter("name == 'Tablet' && price == price_value");
qDJDOQL.declareParameters("double price_value");
List<Product> resultsqDJDOQL = qDJDOQL.setParameters(80.0).executeList();

9.2. SQL查询

JDO支持执行标准SQL:

Query query = pm.newQuery("javax.jdo.query.SQL", "SELECT * FROM PRODUCT");
query.setClass(Product.class);
List<Product> results = query.executeList();

9.3. JPQL查询

支持JPA查询语法:

Query q = pm.newQuery("JPQL",
  "SELECT p FROM " + Product.class.getName() + " p WHERE p.name = 'Laptop'");
List results = (List) q.execute();

10. 总结

本文完整演示了JDO的核心功能:

  • ✅ 构建了完整的CRUD应用
  • ✅ 实现了XML数据持久化
  • ✅ 探索了多种查询机制

完整代码可在GitHub仓库获取。


» 下一篇: Java周报,176