首页 > 解决方案 > org.springframework.orm.jpa.JpaSystemException:必须在调用 save() 之前手动分配此类的 id

问题描述

我正在尝试使用SERIALtype 来生成表的 id。但是在这种情况下,我遇到了一个异常,它说我需要先保存 id。我有另一张这样的桌子,但那张工作正常。

JPA 实体:

@Entity
@Table(name = "pay_appln_data",
        uniqueConstraints = {
                @UniqueConstraint(columnNames = {"dept_ref_no", "application_no"})
                })
public class PayApplnData {
    
    @Id 
    private Long id;
    
    @Column(name = "dept_ref_no")
    private String deptRefNo;
    
    @Column(name = "application_no")
    private String applicationNo;
    
    @Column(name = "depositor_name")
    private String depositorName;
    ...
    ...
}

所用表的 SQL:

CREATE TABLE public.pay_appln_data
(
    id serial NOT NULL,
    dept_ref_no character varying(16) COLLATE pg_catalog."default" NOT NULL,
    application_no character varying(30) COLLATE pg_catalog."default" NOT NULL,
    depositor_name character varying(100) COLLATE pg_catalog."default",
    ...
    ...
    ...
    CONSTRAINT pay_appln_data_pkey PRIMARY KEY (id),
    CONSTRAINT unique_key UNIQUE (dept_ref_no, application_no)
)

DB中的序列presemt是:

CREATE SEQUENCE public.pay_appln_data_id_seq
    INCREMENT 1
    START 1
    MINVALUE 1
    MAXVALUE 2147483647
    CACHE 1;

ALTER SEQUENCE public.pay_appln_data_id_seq
    OWNER TO postgres;

抛出的异常是:

org.springframework.orm.jpa.JpaSystemException: ids for this class must be manually assigned before calling save(): com.rent.mngWithAdmin.model.GRIPSRentPayApplnData; nested exception is org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): com.rent.mngWithAdmin.model.GRIPSRentPayApplnData
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:353)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:255)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
    at com.rent.mngWithAdmin.DAO.GRIPSRentPayApplnDataDAOImpl$$EnhancerBySpringCGLIB$$4516a353.saveOrUpdate(<generated>)
    at com.rent.mngWithAdmin.service.GRIPSApplicationDataServiceImpl.saveOrUpdate(GRIPSApplicationDataServiceImpl.java:21)
    at com.rent.mngWithAdmin.controller.GRIPSRentPayController.rentPayDetails(GRIPSRentPayController.java:301)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
Caused by: org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): com.rent.mngWithAdmin.model.GRIPSRentPayApplnData
    at org.hibernate.id.Assigned.generate(Assigned.java:33)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:115)
    at org.hibernate.event.internal.DefaultMergeEventListener.saveTransientEntity(DefaultMergeEventListener.java:271)
    at org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:243)
    at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:175)
    at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:70)
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102)
    at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:791)
    at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:778)
    at com.rent.mngWithAdmin.DAO.GRIPSRentPayApplnDataDAOImpl.saveOrUpdate(GRIPSRentPayApplnDataDAOImpl.java:22)
    at com.rent.mngWithAdmin.DAO.GRIPSRentPayApplnDataDAOImpl$$FastClassBySpringCGLIB$$4bee3df2.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
    ... 56 more
2021-05-04 12:50:31.403 DEBUG 616 --- [nio-3030-exec-5] org.hibernate.SQL                        : select tbl.next_val from hibernate_sequences tbl where tbl.sequence_name=? for update of tbl
2021-05-04 12:50:31.406 DEBUG 616 --- [nio-3030-exec-5] org.hibernate.SQL                        : update hibernate_sequences set next_val=?  where next_val=? and sequence_name=?
2021-05-04 12:50:31.455 DEBUG 616 --- [nio-3030-exec-5] org.hibernate.SQL                        : select tbl.next_val from hibernate_sequences tbl where tbl.sequence_name=? for update of tbl
2021-05-04 12:50:31.456 DEBUG 616 --- [nio-3030-exec-5] org.hibernate.SQL                        : update hibernate_sequences set next_val=?  where next_val=? and sequence_name=?

我不明白为什么它在搜索,hibernate_sequences而我使用SERIAL类型作为它的 id?

提前谢谢。

标签: javahibernatejpa

解决方案


您必须使用您为 ID 生成创建的序列。

这可以通过以下注释来完成:

@Id
@SequenceGenerator(name = "pay_appln_data_id_seq", sequenceName = "pay_appln_data_id_seq")
@GeneratedValue(strategy = SEQUENCE, generator = "pay_appln_data_id_seq")
private Long id;

推荐阅读