Apache OpenJPA 3.2.2 常用工具与 API 详解
Apache OpenJPA 3.2.2 常用工具与 API 详解:官方命令行工具 PCEnhancer(构建期增强)/SchemaTool/MappingTool/ApplicationIdTool 的用法与实测 help 回显,以及 EntityManagerFactory/EntityManager/EntityTransaction/JPQL 核心 API 与代码示例、增强类验证(javap),含 FAQ,全程实测。
Apache OpenJPA 3.2.2 常用工具与 API 详解
目标:详解 Apache OpenJPA 3.2.2 的官方工具与核心 API 使用。OpenJPA 提供 4 个命令行工具(PCEnhancer、SchemaTool、MappingTool、ApplicationIdTool),通过
java -cp调用其主类执行;编程接口以 JPA 标准 API(EntityManagerFactory/EntityManager/EntityTransaction)为主,辅以 JPQL 查询。本文给出各工具-help实测回显、增强器实测运行与验证(javap),以及 API 代码示例与真实回显。所有示例在 Ubuntu 22.04.5 LTS + JDK 11 + OpenJPA 3.2.2 环境实测。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS
- Java:OpenJDK 11.0.32.1
- OpenJPA 版本:3.2.2
- 全量 jar:
/opt/apache-openjpa-3.2.2/openjpa-all-3.2.2.jar(含全部依赖,直接java -cp使用) - 工程 classpath:
/root/openjpa-demo/target/classes+/tmp/cp.txt(mvn dependency:build-classpath生成) - 示例工程:
/root/openjpa-demo/
二、工具概览
OpenJPA 工具均为 Java 主类,无独立可执行文件,统一以 java -cp <classpath> <主类> [参数] 方式调用(等价 openjpa-all-3.2.2.jar 全量包直接运行):
| 工具 | 主类 | 用途 |
|---|---|---|
| PCEnhancer | org.apache.openjpa.enhance.PCEnhancer | 实体类构建期增强(生成 PersistenceCapable 实现) |
| SchemaTool | org.apache.openjpa.jdbc.schema.SchemaTool | 生成/维护数据库 schema(DDL) |
| MappingTool | org.apache.openjpa.jdbc.meta.MappingTool | 生成/校验实体-表映射与 DDL |
| ApplicationIdTool | org.apache.openjpa.enhance.ApplicationIdTool | 为复合主键实体生成主键类源码 |
| Maven 插件 | openjpa-maven-plugin:enhance | 构建期自动增强(推荐,绑定 process-classes) |
编程 API 概览:
| API 类 | 包 | 作用 |
|---|---|---|
| EntityManagerFactory | javax.persistence | 创建 EntityManager 的工厂(对应持久化单元) |
| EntityManager | javax.persistence | 实体增删改查、事务边界与 JPQL 执行 |
| EntityTransaction | javax.persistence | 资源本地事务(RESOURCE_LOCAL) |
| Persistence | javax.persistence | 引导入口 createEntityManagerFactory("单元名") |
| PersistenceCapable | org.apache.openjpa.enhance | 增强后实体实现的内部接口 |
三、前置条件
export LANG=C.UTF-8 LC_ALL=C.UTF-8
cd /root/openjpa-demo
mvn -q clean process-classes
mvn -q dependency:build-classpath -Dmdep.outputFile=/tmp/cp.txt
- 全量 jar 方式无需工程依赖,直接使用
/opt/apache-openjpa-3.2.2/openjpa-all-3.2.2.jar。
四、官方工具详解
4.1 PCEnhancer(实体增强器)
作用:把 JPA 实体类增强为 org.apache.openjpa.enhance.PersistenceCapable 实现,是 OpenJPA 运行的前置条件(生产默认禁止未增强实体)。
查看用法:
java -cp /opt/apache-openjpa-3.2.2/openjpa-all-3.2.2.jar org.apache.openjpa.enhance.PCEnhancer -help
实测回显:
Usage: java org.apache.openjpa.enhance.PCEnhancer
[-properties/-p <properties file or resource>]
[-<property name> <property value>]*
[-directory/-d <output directory>]
[-addDefaultConstructor/-adc <true/t | false/f>]
[-jdoEnhance/-jdo <true/t | false/f>]
[-enforcePropertyRestrictions/-epr <true/t | false/f>]
[-tmpClassLoader/-tcl <true/t | false/f>]
<class name | .java file | .class file | .jdo file>+
参数速查(实测 help 标注):
| 参数 | 简写 | 默认值 | 作用 |
|---|---|---|---|
| -properties | -p | 无 | 属性文件(可含 openjpa.* 配置) |
| -directory | -d | 当前目录 | 增强输出目录 |
| -addDefaultConstructor | -adc | true | 自动补无参构造器 |
| -jdoEnhance | -jdo | false | 同时生成 JDO 支持 |
| -enforcePropertyRestrictions | -epr | true | 强制执行属性访问限制 |
| -tmpClassLoader | -tcl | true | 使用临时类加载器 |
实测运行(增强 demo/Employee.class):
cd /root/openjpa-demo
java -cp /opt/apache-openjpa-3.2.2/openjpa-all-3.2.2.jar:target/classes org.apache.openjpa.enhance.PCEnhancer demo/Employee.class
实测回显:
100 openjpa-demo INFO [main] openjpa.Tool - Enhancer running on type "class demo.Employee".
验证增强结果:
javap -p target/classes/demo/Employee.class | head -5
实测回显:
Compiled from "Employee.java"
public class demo.Employee implements org.apache.openjpa.enhance.PersistenceCapable {
private long id;
private java.lang.String name;
private java.lang.String department;
💡 说明:增强后的类还包含
pcFieldNames/pcFieldTypes/pcStateManager/pcDetachedState等内部字段与方法(javap -p可见)。生产环境推荐用openjpa-maven-plugin在process-classes阶段自动增强,免手动调用。
4.2 SchemaTool(schema 维护工具)
作用:按 .schema 文件或数据库现网结构生成/维护 DDL。
java -cp /opt/apache-openjpa-3.2.2/openjpa-all-3.2.2.jar org.apache.openjpa.jdbc.schema.SchemaTool -help
实测回显:
Usage: java org.apache.openjpa.jdbc.schema.SchemaTool
[-properties/-p <properties file or resource>]
[-<property name> <property value>]*
[-file/-f <stdout | output file or resource>]
[-ignoreErrors/-i <true/t | false/f>]
[-dropTables/-dt <true/t | false/f>]
[-openjpaTables/-ot <true/t | false/f>]
[-dropSequences/-dsq <true/t | false/f>]
[-sequences/-sq <true/t | false/f>]
[-primaryKeys/-pk <true/t | false/f>]
[-foreignKeys/-fk <true/t | false/f>]
[-indexes/-ix <true/t | false/f>]
[-record/-r <true/t | false/f>]
[-action/-a <add | retain | drop | refresh | build | reflect
| createDB | dropDB | import | export | deleteTableContents>]
<.schema file or resource>*
典型用法:
java -cp /opt/apache-openjpa-3.2.2/openjpa-all-3.2.2.jar \
org.apache.openjpa.jdbc.schema.SchemaTool \
-p /root/openjpa-demo/src/main/resources/META-INF/persistence.xml \
-a export -f stdout
-action/-a:核心动作——build(按映射建表)、reflect(反查库结构)、export/import(导出/导入.schema文件)、drop、deleteTableContents等。-file/-f stdout:DDL 输出到标准输出(可指定输出文件)。- 生产 DBA 场景:
-a export -f schema.sql由开发导出 DDL,DBA 审阅后执行。
4.3 MappingTool(映射与 DDL 生成工具)
作用:生成/校验实体类到数据库表的映射,输出 DDL。
java -cp /opt/apache-openjpa-3.2.2/openjpa-all-3.2.2.jar org.apache.openjpa.jdbc.meta.MappingTool -help
实测回显:
Usage: java org.apache.openjpa.jdbc.meta.MappingTool
[-properties/-p <properties file or resource>]
[-<property name> <property value>]*
[-file/-f <stdout | output file or resource>]
[-schemaFile/-sf <stdout | output file or resource>]
[-sqlFile/-sql <stdout | output file or resource>]
[-sqlEncode/-se <Java character set encoding like UTF-8>]
[-schemaAction/-sa <add | retain | drop | refresh | build | none>]
[-schemas/-s <schemas and tables>]
[-readSchema/-rs <true/t | false/f>]
[-primaryKeys/-pk <true/t | false/f>]
[-foreignKeys/-fk <true/t | false/f>]
[-indexes/-ix <true/t | false/f>]
[-dropTables/-dt <true/t | false/f>]
[-openjpaTables/-ot <true/t | false/f>]
[-dropSequences/-dsq <true/t | false/f>]
[-sequences/-sq <true/t | false/f>]
[-ignoreErrors/-i <true/t | false/f>]
[-action/-a <refresh | add | buildSchema | drop | validate | import
| export>]
<class name | .java file | .class file | .jdo file | .orm file | .mapping file>*
典型用法:
java -cp /opt/apache-openjpa-3.2.2/openjpa-all-3.2.2.jar:target/classes \
org.apache.openjpa.jdbc.meta.MappingTool \
-p /root/openjpa-demo/src/main/resources/META-INF/persistence.xml \
-a buildSchema -sql stdout demo.Employee
-action/-a buildSchema:按实体映射直接建表(等价 persistence.xml 的SynchronizeMappings=buildSchema,可离线独立执行);validate校验映射与库表一致性;refresh/add/drop维护既有结构。-sql stdout:把生成的 SQL 输出到标准输出,便于审阅。
4.4 ApplicationIdTool(主键类生成工具)
作用:为使用复合主键(@IdClass/@EmbeddedId)的实体生成应用主键类源码。
java -cp /opt/apache-openjpa-3.2.2/openjpa-all-3.2.2.jar org.apache.openjpa.enhance.ApplicationIdTool -help
实测回显:
Usage: java org.apache.openjpa.enhance.ApplicationIdTool
[-properties/-p <properties file or resource>]
[-<property name> <property value>]*
[-ignoreErrors/-i <true/t | false/f>]*
[-directory/-d <output directory>]
[-name/-n <id class name>]
[-suffix/-s <id class suffix>]
[-token/-t <token>]
[-codeFormat/-cf.<property name> <property value>]*
<class name | .java file | .class file | .jdo file>+
典型用法:
java -cp /opt/apache-openjpa-3.2.2/openjpa-all-3.2.2.jar:target/classes \
org.apache.openjpa.enhance.ApplicationIdTool \
-d src/main/java -n demo.EmployeeId demo.Employee
-directory/-d:生成的.java输出目录。-name/-n:生成的主键类类名(默认EmployeeId)。-suffix/-s:类名后缀(默认Id)。-token/-t:拆分字段名的分隔符。
4.5 Maven 插件方式(推荐)
构建期增强推荐用 openjpa-maven-plugin(pom 配置见《Apache OpenJPA 3.2.2 构建并运行示例应用指南》),构建命令与实测回显:
cd /root/openjpa-demo
mvn -q clean process-classes
79 openjpa-demo INFO [main] openjpa.Tool - Enhancer running on type "class demo.Employee".
五、核心 API 详解
5.1 Persistence 与 EntityManagerFactory
引导入口,读取 persistence.xml 中名为 openjpa-demo 的持久化单元:
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("openjpa-demo");
Persistence.createEntityManagerFactory(String):按持久化单元名创建工厂(单例化使用,进程内一般只建一次)。emf.createEntityManager():每次业务操作创建EntityManager。emf.close():进程结束时释放(实测末尾调用后进程正常退出)。
5.2 EntityManager 与 EntityTransaction(CRUD 实测)
新增、更新、删除均需在事务中执行;查询不强制要求事务:
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(new Employee("张三", "研发部", 18000.0)); // 新增
tx.commit();
tx = em.getTransaction();
tx.begin();
Employee e = em.find(Employee.class, 2L); // 按主键查询
e.setSalary(16000.0); // 托管实体修改即更新
tx.commit();
tx = em.getTransaction();
tx.begin();
Employee e3 = em.find(Employee.class, 3L);
em.remove(e3); // 删除
tx.commit();
方法速查:
| 方法 | 作用 |
|---|---|
| persist(Object) | 新增托管实体 |
| find(Class, Object) | 按主键查询(返回托管实体) |
| merge(Object) | 合并游离实体(返回托管副本) |
| remove(Object) | 删除实体 |
| createQuery(String, Class) | 创建 TypedQuery(类型化 JPQL) |
| createQuery(String) | 创建 Query(通用 JPQL) |
| flush() | 立即同步到数据库 |
| close() | 释放 EntityManager |
5.3 JPQL 查询(实测回显)
类型化查询 + 命名参数:
TypedQuery<Employee> q = em.createQuery(
"select e from Employee e where e.department = :dept order by e.salary desc",
Employee.class);
q.setParameter("dept", "研发部");
List<Employee> devs = q.getResultList();
实测回显(2 条命中,按薪资降序):
== JPQL 条件查询 研发部 (2 条) ==
Employee[id=3, name=王五, department=研发部, salary=22000.00]
Employee[id=1, name=张三, department=研发部, salary=18000.00]
聚合查询:
Query avgQuery = em.createQuery(
"select avg(e.salary) from Employee e where e.department = :dept");
avgQuery.setParameter("dept", "研发部");
Object avg = avgQuery.getSingleResult();
实测回显:
== JPQL 聚合查询 研发部平均薪资: 20000.0 ==
计数查询:
long count = (Long) em.createQuery("select count(e) from Employee e").getSingleResult();
实测回显:
== 删除后员工总数: 2 ==
💡 说明:JPQL 中
Employee为实体名(非表名)、e为别名;OpenJPA 编译为原生 SQL(如SELECT t0.id, t0.department, t0.name, t0.salary FROM employees t0 WHERE (t0.department = ?) ORDER BY t0.salary DESC),可通过SQL=TRACE日志核对。
六、注意事项
- 工具均需完整 classpath:SchemaTool/MappingTool 连接数据库时会加载 JDBC 驱动,请用
openjpa-all-3.2.2.jar(内置依赖)或显式加入驱动 jar。 - 增强只做一次:同一 class 重复执行 PCEnhancer 无害但多余;构建期增强后勿再覆盖 target/classes 下的原始 class。
- 工具类日志:工具运行日志走
openjpa.Tool频道,可用-p属性文件中的openjpa.Log调级别(如Tool=DEBUG看内部步骤)。 - 事务边界:
RESOURCE_LOCAL模式下必须手动tx.begin()/commit(),忘记 commit 会导致数据未落库(事务自动回滚时抛RollbackException)。
七、常见问题
Q1:java -cp openjpa-all-3.2.2.jar PCEnhancer 找不到主类?
A:确认主类全名大小写:org.apache.openjpa.enhance.PCEnhancer(不是 PCEnhancer 简写);且 jar 路径正确。
Q2:SchemaTool/MappingTool 连库报 ClassNotFoundException?
A:classpath 缺少数据库驱动。加 -cp openjpa-all-3.2.2.jar:<驱动jar>(Derby 驱动在官方包 lib/derby-10.14.2.0.jar),或在 -p 属性中确认 javax.persistence.jdbc.driver。
Q3:增强前后行为有什么差异?
A:增强前(未增强 + RuntimeUnenhancedClasses=supported)实测启动输出警告「Creating subclass ... less efficient and will consume more memory」,且一对多/多对一懒加载失效;增强后无警告,javap 可见类实现 PersistenceCapable。
Q4:如何离线获得工具?
A:官方二进制包 apache-openjpa-3.2.2-binary.zip 解压后的 openjpa-all-3.2.2.jar 即全量工具集,无需 Maven 仓库(实测 PCEnhancer 直接运行成功)。
八、参考链接
- OpenJPA 工具文档(Ref Guide – Tools):https://openjpa.apache.org/builds/3.2.2/apache-openjpa/docs/manual/ref_guide_tools.html
- OpenJPA API 文档:https://openjpa.apache.org/builds/3.2.2/apache-openjpa/apidocs/
- OpenJPA 项目主页:https://openjpa.apache.org/