Spring 3.1.0升级:OpenJPA适配Jakarta Persistence遇增强异常求助
Spring 3.1.0 + OpenJPA 迁 Jakarta Persistence 问题解决指南
一、先明确:OpenJPA 支持 Jakarta Persistence 吗?
OpenJPA 从 3.0.0 版本开始正式支持 Jakarta Persistence 2.2/3.0,2.x 及以下版本只认旧的 javax.persistence 包。所以第一步必须确认你用的 OpenJPA 版本是不是 ≥3.0.0,这是核心前提。
二、运行时「实体未增强」异常的排查要点
你碰到的 MetaDataException: The type "class com.x.x.x.xEntity" has not been enhanced,说白了就是 OpenJPA 的字节码增强步骤没适配新的 Jakarta 包路径,按下面几点逐一排查:
1. 先把依赖版本搞对
把所有 javax.persistence 相关依赖换成 Jakarta 版本,同时升级 OpenJPA 到兼容版本:
<!-- pom.xml 示例 --> <dependency> <groupId>org.apache.openjpa</groupId> <artifactId>openjpa</artifactId> <version>3.2.2</version> <!-- 选最新的 Jakarta 兼容版 --> </dependency> <dependency> <groupId>jakarta.persistence</groupId> <artifactId>jakarta.persistence-api</artifactId> <version>2.2.3</version> <!-- 对应 Jakarta Persistence 2.2 --> </dependency>
2. 修正 persistence.xml 的 schema 配置
把旧的 javax 路径 schema 换成 Jakarta 的,别再用 sun 那个旧地址了:
<!-- src/main/resources/META-INF/persistence.xml --> <persistence xmlns="https://jakarta.ee/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_2_2.xsd" version="2.2"> <persistence-unit name="myPU" transaction-type="RESOURCE_LOCAL"> <class>com.x.x.x.xEntity</class> <properties> <!-- 强制要求增强,避免运行时踩坑 --> <property name="openjpa.RuntimeUnenhancedClasses" value="unsupported"/> <property name="openjpa.BrokerImpl" value="jdbc"/> <!-- 数据库连接配置,用 jakarta 前缀也可以,OpenJPA 3.x 兼容两种 --> <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/mydb"/> <property name="javax.persistence.jdbc.user" value="root"/> <property name="javax.persistence.jdbc.password" value="password"/> </properties> </persistence-unit> </persistence>
3. 字节码增强插件必须升级
如果用 Maven 做增强,插件必须升到 3.x 版本,不然它找不到 Jakarta 的注解:
<build> <plugins> <plugin> <groupId>org.apache.openjpa</groupId> <artifactId>openjpa-maven-plugin</artifactId> <version>3.2.2</version> <executions> <execution> <id>enhance</id> <phase>process-classes</phase> <goals> <goal>enhance</goal> </goals> </execution> </executions> <configuration> <includes>com/x/x/x/*.class</includes> <!-- 你的实体类路径,注意用斜杠 --> <addDefaultConstructor>true</addDefaultConstructor> <!-- 自动加无参构造,省得自己写 --> <enforcePropertyRestrictions>true</enforcePropertyRestrictions> </configuration> <dependencies> <dependency> <groupId>org.apache.openjpa</groupId> <artifactId>openjpa</artifactId> <version>3.2.2</version> </dependency> </dependencies> </plugin> </plugins> </build>
IDE 运行的话,要么手动执行 mvn process-classes 触发增强,要么在 IDE 构建配置里绑定这个插件的执行阶段。
4. Spring 配置适配 Jakarta
Spring 3.1.0 是 Jakarta 版本,配置上注意用对应的 JPA 组件,示例如下:
@Configuration @EnableTransactionManagement public class JpaConfig { @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setPersistenceUnitName("myPU"); // 对应 persistence.xml 里的 PU 名称 em.setDataSource(dataSource()); OpenJpaVendorAdapter vendorAdapter = new OpenJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); return em; } @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/mydb"); dataSource.setUsername("root"); dataSource.setPassword("password"); return dataSource; } @Bean public PlatformTransactionManager transactionManager(EntityManagerFactory emf) { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(emf); return transactionManager; } }
三、完整代码示例
1. 实体类(用 Jakarta 注解)
package com.x.x.x; import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @Entity public class xEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; // 必须有无参构造函数,OpenJPA 增强要求的 public xEntity() {} // getter/setter public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
2. Repository(Spring Data JPA)
package com.x.x.x; import org.springframework.data.jpa.repository.JpaRepository; public interface xEntityRepository extends JpaRepository<xEntity, Long> { }
3. 启动测试类
package com.x.x.x; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { ApplicationContext context = SpringApplication.run(DemoApplication.class, args); xEntityRepository repo = context.getBean(xEntityRepository.class); xEntity entity = new xEntity(); entity.setName("Test Jakarta"); repo.save(entity); System.out.println("保存成功:" + repo.findById(entity.getId()).get().getName()); } }
四、容易遗漏的坑总结
- 版本不匹配:用了 OpenJPA 2.x 配 Jakarta 包,必踩坑,必须升 3.x
- 增强插件没升级:Maven 插件还是旧版本,识别不了 Jakarta 注解
- persistence.xml 没换 schema:还在用 sun 的旧路径,元数据解析异常
- 实体类缺无参构造:OpenJPA 增强要求必须有公共无参构造函数
内容的提问来源于stack exchange,提问作者Abha
相关产品推荐
相关产品推荐

