You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 19:44:54