Apache JDO 3.2.1 配置参数详解

详解 Apache JDO 3.2.1 + DataNucleus 6.0 的运行时配置:编程式 Properties 与 jdoconfig.xml 两种创建方式、javax.jdo.option 标准属性、datanucleus 扩展属性、连接 URL、增强插件参数与 JDOQL 配置,含实测示例

Apache JDOJDOApacheJava配置详解参数调优2026/10/14

Apache JDO 3.2.1 配置参数详解

配置分两层:javax.jdo.option.* 是 JDO 规范标准属性,任何实现都认识;datanucleus.* 是 DataNucleus 6.0 的实现扩展属性。本文实测环境:DataNucleus 6.0.11 + api-jdo 6.0.5 + H2 2.2.224 + Temurin 17。标注"实测"的输出均为容器内真实回显。

一、PMF 创建的两种方式

PersistenceManagerFactory(PMF)是 JDO 的会话工厂,等价于 JPA 的 EntityManagerFactory。两种创建方式:

方式载体适用
编程式 PropertiesJDOHelper.getPersistenceManagerFactory(props)单元测试、内存库、想避免 XML 失败面(本文实测采用)
jdoconfig.xmlMETA-INF/jdoconfig.xml + JDOHelper.getPersistenceManagerFactory("pu-name")传统工程、多持久化单元切换

1.1 编程式(实测通过的最小集)

Properties props = new Properties();
props.setProperty("javax.jdo.PersistenceManagerFactoryClass",
        "org.datanucleus.api.jdo.JDOPersistenceManagerFactory");
props.setProperty("javax.jdo.option.ConnectionURL",
        "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1");
props.setProperty("datanucleus.schema.autoCreateAll", "true");
PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props);

实测运行结果(节选):

[persist] 3 objects committed
[JDOQL] age > 25 -> 2 rows
  Person{id=3, name='Carol', age=27}
  Person{id=1, name='Alice', age=30}

1.2 jdoconfig.xml(参考,本文未实测)

<jdoconfig xmlns="http://xmlns.jcp.org/xml/ns/jdo/jdoconfig">
    <persistence-manager-factory name="demo">
        <property name="javax.jdo.option.ConnectionURL" value="jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1"/>
        <property name="datanucleus.schema.autoCreateAll" value="true"/>
    </persistence-manager-factory>
</jdoconfig>

放 src/main/resources/META-INF/jdoconfig.xml,运行时 JDOHelper.getPersistenceManagerFactory("demo")。

二、javax.jdo.option 标准属性表

属性必填示例值说明
javax.jdo.PersistenceManagerFactoryClass是org.datanucleus.api.jdo.JDOPersistenceManagerFactory实现类
javax.jdo.option.ConnectionURL是jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1JDBC 连接串(RDBMS 场景)
javax.jdo.option.ConnectionDriverName视驱动org.h2.Driver显式指定驱动类,多数驱动可自动识别
javax.jdo.option.ConnectionUserName生产必填griffin用户名
javax.jdo.option.ConnectionPassword生产必填***口令
javax.jdo.option.ConnectionFactoryName二选一java:comp/env/jdbc/demoJNDI 数据源名(容器托管时替代 URL 三件套)
javax.jdo.option.ReadOnly否truePMF 级只读
javax.jdo.option.Multithreaded否true允许同一 PM 跨线程使用(默认 false,慎开)
javax.jdo.option.Optimistic否true乐观事务(版本号校验)
javax.jdo.option.RestoreValues否true回滚时恢复字段值
javax.jdo.option.RetainValues否true提交后保留字段值
javax.jdo.option.NontransactionalRead否true允许事务外读
javax.jdo.option.Mapping否mysqlORM 映射文件命名空间(多库共用注解时)

三、DataNucleus 关键扩展属性

属性实测值说明
datanucleus.schema.autoCreateAlltrue(实测)自动建表建约束,演示/开发利器;生产建议显式 DDL
datanucleus.schema.autoCreateTables—只自动建表(autoCreateAll 的细分)
datanucleus.schema.validateTables—启动时校验表结构
datanucleus.ConnectionURL—与 javax.jdo.option.ConnectionURL 等价的 DN 写法
datanucleus.connectionPoolType—连接池实现(DBCP/HikariCP,需加对应依赖)
datanucleus.connectionPool.maxPoolSize—池上限(配合 HikariCP 等)
datanucleus.autoStartMechanism—启动时扫描已有数据类(None/Table/Classes)
datanucleus.identifierCase—标识符大小写策略(MixedCase/UpperCase 等)
datanucleus.cache.level2.type—二级缓存(none/javax.cache);默认 none
datanucleus.datastoreTransactionTimeout—数据store事务超时(毫秒)
datanucleus.persistenceByReachabilityAtCommit—提交时可达性分析开关

实测提示:未配 log4j2 绑定时,DataNucleus 的 SQL/建表日志不会输出(实测 grep CREATE TABLE 运行日志为空)。要看 SQL 需引入 log4j-core 并将 DataNucleus.Datastore 日志级别调 DEBUG。

四、连接 URL 与数据库矩阵

数据库ConnectionURL驱动依赖
H2 内存jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1com.h2database:h2
H2 文件jdbc:h2:file:./data/demo同上
MySQL 8jdbc:mysql://host:3306/demo?useSSL=falsecom.mysql:mysql-connector-j
PostgreSQLjdbc:postgresql://host:5432/demoorg.postgresql:postgresql
Derbyjdbc:derby:./data/demo;create=trueorg.apache.derby:derby

URL 中的连接参数(如 H2 的 DB_CLOSE_DELAY=-1)直接控制行为;实测 DB_CLOSE_DELAY=-1 是跨 PM 访问同一内存库的关键,不加则每个连接各得一个空库。

五、datanucleus-maven-plugin 增强配置

<plugin>
    <groupId>org.datanucleus</groupId>
    <artifactId>datanucleus-maven-plugin</artifactId>
    <version>6.0.1</version>
    <configuration>
        <verbose>true</verbose>
    </configuration>
    <executions>
        <execution>
            <phase>process-classes</phase>
            <goals><goal>enhance</goal></goals>
        </execution>
    </executions>
</plugin>
参数默认说明
verbosefalse打印增强明细(实测输出 ENHANCED (Persistable) : demo.Person)
apiJDO持久化 API(JDO/JPA)
log4jConfiguration—增强器日志配置文件路径
persistenceUnitName—按 persistence.xml 选择增强范围
includes/excludes—类文件 glob 过滤
forktrue独立 JVM 运行增强器

<phase>process-classes</phase> 把增强挂在编译后、打包前;实测增强耗时 input=69 ms, enhance=56 ms, total=125 ms(1 个类)。

实测排障要点:6.0.1 将增强器 stderr 转发为 Maven [ERROR] 行,内容实为 INFO,不代表失败——以 ENHANCED (Persistable) 行 + BUILD SUCCESS 为准:

[INFO] DataNucleus Enhancer (version 6.0.11) for API "JDO"
ENHANCED (Persistable) : demo.Person
DataNucleus Enhancer completed with success for 1 classes. Timings : input=69 ms, enhance=56 ms, total=125 ms.

六、JDOQL 查询配置与参数化

6.1 单字符串 JDOQL(实测通过)

Query<Person> q = pm2.newQuery("javax.jdo.query.JDOQL",
    "SELECT FROM demo.Person WHERE age > 25 ORDER BY age ASC");

语法骨架:SELECT [DISTINCT] FROM 全限定类名 [WHERE 条件] [PARAMETERS 声明] [ORDER BY] [GROUP BY]。实测命中 2 行且升序(见 1.1 回显)。

6.2 参数化(生产必用,防注入)

Query<Person> q = pm.newQuery(Person.class, "age > :minAge");
List<Person> rows = (List<Person>) q.execute(25);

或显式声明:q.declareParameters("int minAge"); q.setFilter("age > minAge"); q.execute(25);

6.3 主键回读(实测)

Person bob = pm2.getObjectById(Person.class, 2L);
// [getObjectById] id=2 -> Person{id=2, name='Bob', age=22}

getObjectById 走主键索引直达,不产生集合扫描,是最快的单条读取方式。

七、事务参数与生命周期

Transaction tx = pm.currentTransaction();
tx.begin();
try { /* 操作 */ tx.commit(); }
finally { if (tx.isActive()) tx.rollback(); }
pm.close();
关注点配置/做法
乐观锁PMF 属性 javax.jdo.option.Optimistic=true + 实体加 @Version 字段
跨 PM 读内存库H2 URL DB_CLOSE_DELAY=-1(实测必需)
提交后继续读对象javax.jdo.option.RetainValues=true
回滚恢复字段javax.jdo.option.RestoreValues=true
大批量插入每 N 条 tx.commit() 分段提交,避免长事务

八、FAQ

Q1:Properties 和 jdoconfig.xml 混用时优先级? 编程式传入的 Properties 为准;JDOHelper(name) 方式只读 jdoconfig.xml。

Q2:autoCreateAll 生产环境能用吗? 不建议,表结构漂移难审计;生产用显式 DDL 或 validateTables 启动校验。

Q3:连接池怎么配? datanucleus.connectionPoolType=HikariCP 并引入 HikariCP 依赖,再用 datanucleus.connectionPool.* 细调。

Q4:密码明文写在 Properties 里安全吗? 不安全,从环境变量/JNDI 注入:props.setProperty("javax.jdo.option.ConnectionPassword", System.getenv("DB_PWD"))。

Q5:为什么我改了实体字段但库里没变? autoCreateAll 只建不改;字段变更需手工 ALTER 或清库重建。

Q6:Multithreaded=true 就线程安全了吗? 只是解除"单 PM 单线程"限制,业务层仍需自行同步;常规做法是每线程各取 PM。

Q7:JDOQL 能做聚合吗? 支持 SUM/COUNT/MIN/MAX/AVG + GROUP BY/HAVING;复杂报表建议原生 SQL(pm.newQuery("javax.jdo.query.SQL", "..."))。

Q8:如何关闭二级缓存? 默认就是 none;显式声明 datanucleus.cache.level2.type=none 防止依赖传递引入意外配置。

Q9:enhance 只增强部分类怎么配? <includes><include>demo/*.class</include></includes>(插件 configuration 段)。

Q10:javax.jdo.option.Mapping 什么时候需要? 同一套注解要按数据库微调映射时(如 MySQL/Oracle 各一份 mapping 文件),普通项目留空。

参考链接