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

设置Hibernate 'update'表生成策略后仍不存在laptop_seq表,POST请求保存Laptop实体时抛出异常

设置Hibernate 'update'表生成策略后仍不存在laptop_seq表,POST请求保存Laptop实体时抛出异常

我这边有一个Quarkus项目,包含以下代码和配置,在发送POST请求时遇到了Hibernate相关的异常,具体情况如下:

1. 实体类与REST资源类

这是继承自PanacheEntity的Laptop实体类,以及对应的处理POST请求的LaptopResource资源类:

import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.Entity;

@Entity
public class Laptop extends PanacheEntity {
    private String name;
    private String brand;
    private int ram;
    private int externalStorage;
}
import eagle.tailung.entity.Laptop;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;

import java.net.URI;
import java.util.List;
@Path("/laptop/")
public class LaptopResource {
    @POST
    @Transactional
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response addLaptop(Laptop laptop){
        Laptop.persist(laptop);
        if(laptop.isPersistent()){
            return Response.created(URI.create("/laptop/"+laptop.id)).build();
        }
        return Response.status(Response.Status.BAD_REQUEST).build();
    }
}

2. 应用配置文件(application.properties)

quarkus.datasource.db-kind=mysql 
quarkus.datasource.username=username
quarkus.datasource.password=password

quarkus.datasource.jdbc.url=jdbc:mysql://localhost:3306/hibernate_orm_test
quarkus.datasource.jdbc.max-size=16
quarkus-hibernate-orm.database.generation=update

3. 遇到的问题

当我向/laptop发送POST请求时,抛出了Hibernate异常,请求在Swagger UI中的情况如下:
Swagger UI中的POST请求

完整异常栈信息:

"details": "Error id bedefe4e-3ca0-4731-b2fa-d183959db81d-5, org.jboss.resteasy.spi.UnhandledException: org.hibernate.HibernateException: Could not apply work",
"stack": "org.jboss.resteasy.spi.UnhandledException: org.hibernate.HibernateException: Could not apply work
    at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:107)
    at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:344)
    at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:205)
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:452)
    at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invokePropagateNotFound$6(SynchronousDispatcher.java:275)
    at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:154)
    at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:321)
    at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:157)
    at org.jboss.resteasy.core.SynchronousDispatcher.invokePropagateNotFound(SynchronousDispatcher.java:260)
    at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:86)
    at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:151)
    at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler$1.run(VertxRequestHandler.java:97)
    at io.quarkus.vertx.core.runtime.VertxCoreRecorder$15.runWith(VertxCoreRecorder.java:639)
    at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2675)
    at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2654)
    at org.jboss.threads.EnhancedQueueExecutor.runThreadBody(EnhancedQueueExecutor.java:1627)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1594)
    at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:11)
    at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:11)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: org.hibernate.HibernateException: Could not apply work
    at org.hibernate.resource.transaction.backend.jta.internal.JtaIsolationDelegate.doInNewTransaction(JtaIsolationDelegate.java:173)
    at org.hibernate.resource.transaction.backend.jta.internal.JtaIsolationDelegate.lambda$delegateWork$3(JtaIsolationDelegate.java:90)
    at org.hibernate.resource.transaction.backend.jta.internal.JtaIsolationDelegate.doInSuspendedTransaction(JtaIsolationDelegate.java:125)
    at org.hibernate.resource.transaction.backend.jta.internal.JtaIsolationDelegate.delegateWork(JtaIsolationDelegate.java:88)
    at org.hibernate.id.enhanced.TableStructure$1.getNextValue(TableStructure.java:135)
    at org.hibernate.id.enhanced.PooledLoOptimizer.generate(PooledLoOptimizer.java:65)
    at org.hibernate.id.enhanced.SequenceStyleGenerator.generate(SequenceStyleGenerator.java:585)
    at org.hibernate.id.IdentifierGenerator.generate(IdentifierGenerator.java:135)
    at org.hibernate.event.internal.AbstractSaveEventListener.generateId(AbstractSaveEventListener.java:155)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:126)
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:177)
    at org.hibernate.event.internal.DefaultPersistEventListener.persist(DefaultPersistEventListener.java:95)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:79)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:55)
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:761)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:745)
    at io.quarkus.hibernate.orm.runtime.session.TransactionScopedSession.persist(TransactionScopedSession.java:146)
    at org.hibernate.engine.spi.SessionLazyDelegator.persist(SessionLazyDelegator.java:282)
    at org.hibernate.Session_OpdLahisOZ9nWRPXMsEFQmQU03A_Synthetic_ClientProxy.persist(Unknown Source)
    at io.quarkus.hibernate.orm.panache.common.runtime.AbstractJpaOperations.persist(AbstractJpaOperations.java:105)
    at io.quarkus.hibernate.orm.panache.common.runtime.AbstractJpaOperations.persist(AbstractJpaOperations.java:100)
    at io.quarkus.hibernate.orm.panache.common.runtime.AbstractJpaOperations.persist(AbstractJpaOperations.java:116)
    at io.quarkus.hibernate.orm.panache.PanacheEntityBase.persist(PanacheEntityBase.java:768)
    at eagle.tailung.entity.Laptop.persist(Laptop.java)
    at eagle.tailung.Resource.LaptopResource.addLaptop(LaptopResource.java:24)
    at eagle.tailung.Resource.LaptopResource_Subclass.addLaptop$$superforward(Unknown Source)
    at eagle.tailung.Resource.LaptopResource_Subclass$$function$$3.apply(Unknown Source)
    at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:73)
    at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:62)
    at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.invokeInOurTx(TransactionalInterceptorBase.java:136)
    at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.invokeInOurTx(TransactionalInterceptorBase.java:107)
    at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired.doIntercept(TransactionalInterceptorRequired.java:38)
    at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.intercept(TransactionalInterceptorBase.java:61)
    at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired.intercept(TransactionalInterceptorRequired.java:32)
    at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired_Bean.intercept(Unknown Source)
    at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
    at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:30)
    at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:27)
    at eagle.tailung.Resource.LaptopResource_Subclass.addLaptop(Unknown Source)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:154)
    at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:118)
    at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:560)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:452)
    at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:413)
    at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:321)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:415)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:378)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:356)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:70)
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:429)
    ... 17 more
Caused by: org.hibernate.HibernateException: Unable to perform isolated work
    at org.hibernate.resource.transaction.backend.jta.internal.JtaIsolationDelegate.doTheWork(JtaIsolationDelegate.java:193)
    at org.hibernate.resource.transaction.backend.jta.internal.JtaIsolationDelegate.lambda$delegateWork$2(JtaIsolationDelegate.java:90)
    at org.hibernate.resource.transaction.backend.jta.internal.JtaIsolationDelegate.doInSuspendedTransaction(JtaIsolationDelegate.java:125)
    ...

问题分析与解决方案

从异常栈能看出,核心问题是:PanacheEntity默认采用基于序列的ID生成策略,但MySQL不支持原生序列,Hibernate会通过创建laptop_seq表来模拟序列;而你配置的quarkus-hibernate-orm.database.generation=update只会更新已存在的表结构,不会主动创建这个模拟序列的新表,导致保存实体时找不到序列表抛出异常。

这里提供两种直接的解决办法:

方法1:适配MySQL自增主键,修改实体类的ID生成策略

放弃继承PanacheEntity,改为继承PanacheEntityBase,手动定义适配MySQL的自增ID:

import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class Laptop extends PanacheEntityBase {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long id;
    private String name;
    private String brand;
    private int ram;
    private int externalStorage;
}

这种方式完全适配MySQL的自增主键特性,不需要额外的序列表,是最贴合MySQL生态的方案。

方法2:初始化序列表后改回原配置

  • 临时启动初始化:把quarkus-hibernate-orm.database.generation临时改为create,启动一次项目,Hibernate会自动创建所有需要的表(包括laptop_seq),之后再改回update即可。
  • 手动创建序列表:直接在MySQL中执行SQL创建laptop_seq表:
    CREATE TABLE laptop_seq (
        next_val BIGINT
    ) ENGINE=InnoDB;
    INSERT INTO laptop_seq VALUES (1);
    

备注:内容来源于stack exchange,提问作者mildgrey

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 03:44:32