hibernate在使用复合主键保存实体时抛出列索引超出预期范围

kg7wmglp  于 2021-07-06  发布在  Java
关注(0)|答案(2)|浏览(273)

我遇到过一个非常奇怪的冬眠动物的行为,也许我不知道什么。我的hibernate版本是5.4.12。
当我试图用复合主键保存实体时,hibernate绑定了第5个参数,而我只有4个参数。我已经试着解决这个问题好几天了,但没有结果。
这是故障实体:

@Entity
@Table(name = "asset_asset_type_attribute")
@Getter
@Setter
@IdClass(AssetAttributeId.class)
public class AssetAssetTypeAttribute {

    @Id
    @Column(name = "tenant_id", insertable = false, updatable = false)
    private Long tenantId;

    @Id
    @Column(name = "asset_id", insertable = false, updatable = false)
    private Long assetId;

    @Id
    @Column(name = "asset_type_attribute_id")
    private Long assetTypeAttributeId;

    @Id
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "asset_id", referencedColumnName = "id"),
            @JoinColumn(name = "tenant_id", referencedColumnName = "tenant_id"),
    })
    @JsonIgnore
    private Asset asset;

    @Id
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "asset_type_attribute_id", referencedColumnName = "id", insertable = false, updatable = false)
    private AssetTypeAttribute assetTypeAttribute;

    private String value;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class AssetAttributeId implements Serializable {
    private Long assetId;
    private Long assetTypeAttributeId;
    private Long tenantId;
}

其他相关实体:

@Entity
@Table(name = "asset")
@Getter
@Setter
@IdClass(AssetId.class)
public class Asset {
    @Id
    private Long id;

    @Id
    @Column(name = "tenant_id")
    private Long tenantId;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "asset", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<AssetAssetTypeAttribute> assetAssetTypeAttributes;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
public class AssetId implements Serializable {
    private Long id;
    private Long tenantId;
}

@Entity
@Table(name = "asset_type_attribute")
@Getter
@Setter
public class AssetTypeAttribute {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "assetTypeAttribute", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<AssetAssetTypeAttribute> assetAssetTypeAttributes;
}

这是我在资产实体中放置assetasettypeattribute的方式

AssetAssetTypeAttribute assetAssetTypeAttribute = new AssetAssetTypeAttribute();

assetAssetTypeAttribute.setAssetTypeAttribute(assetTypeAttribute);
assetAssetTypeAttribute.setAsset(asset);
assetAssetTypeAttribute.setValue(entry.getValue());
asset.getAssetAssetTypeAttributes().add(assetAssetTypeAttribute);

这是我保存实体的方式:

Session session = sessionFactory.openSession();
session.setHibernateFlushMode(FlushMode.COMMIT);
Transaction transaction = session.beginTransaction();

try {
    session.saveOrUpdate(asset);
    for (AssetAssetTypeAttribute assetTypeAttribute : asset.getAssetAssetTypeAttributes()) {
        session.saveOrUpdate(assetTypeAttribute);
    }

    transaction.commit();
    return asset;
} catch (Exception e) {
    transaction.rollback();
    throw e;
} finally {
    session.close();
}

当hibernate试图保存assetassettypeattribute实体时,它会生成以下内容:

2020-11-19 02:49:01,250 DEBUG [http-nio-8080-exec-7] org.hibernate.engine.jdbc.spi.SqlStatementLogger: insert into asset_asset_type_attribute (asset_id, tenant_id, value, asset_type_attribute_id) values (?, ?, ?, ?)
2020-11-19 02:49:01,250 TRACE [http-nio-8080-exec-7] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [1] as [BIGINT] - [57]
2020-11-19 02:49:01,251 TRACE [http-nio-8080-exec-7] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [2] as [BIGINT] - [1]
2020-11-19 02:49:01,251 TRACE [http-nio-8080-exec-7] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [3] as [VARCHAR] - [231]
2020-11-19 02:49:01,251 TRACE [http-nio-8080-exec-7] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [4] as [BIGINT] - [null]
2020-11-19 02:49:01,251 TRACE [http-nio-8080-exec-7] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [5] as [BIGINT] - [1]

因此我在postgresql级别得到了一个例外:

javax.persistence.PersistenceException: org.hibernate.exception.DataException: could not insert: [com.bitraid.servicedesk.entity.AssetAssetTypeAttribute]
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1356)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:443)
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3202)
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2370)
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:447)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281)
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
    at com.bitraid.servicedesk.service.impl.AssetServiceImpl.saveAsset(AssetServiceImpl.java:245)
    at com.bitraid.servicedesk.service.impl.AssetServiceImpl.create(AssetServiceImpl.java:102)
    at com.bitraid.servicedesk.controllers.AssetController.create(AssetController.java:27)
    at com.bitraid.servicedesk.controllers.AssetController$$FastClassBySpringCGLIB$$9d47bc91.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.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:69)
    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.bitraid.servicedesk.controllers.AssetController$$EnhancerBySpringCGLIB$$7255f121.create(<generated>)
    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 com.bitraid.servicedesk.security.JwtTokenFilter.doFilter(JwtTokenFilter.java:35)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at com.bitraid.servicedesk.security.JwtTokenFilter.doFilter(JwtTokenFilter.java:35)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
    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:1594)
    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.exception.DataException: could not insert: [com.bitraid.servicedesk.entity.AssetAssetTypeAttribute]
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:115)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3253)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3760)
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:107)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
    at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478)
    at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:348)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102)
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1352)
    ... 107 more
Caused by: org.postgresql.util.PSQLException: The column index is out of range: 5, number of columns: 4.
    at org.postgresql.core.v3.SimpleParameterList.bind(SimpleParameterList.java:65)
    at org.postgresql.core.v3.SimpleParameterList.setBinaryParameter(SimpleParameterList.java:132)
    at org.postgresql.jdbc.PgPreparedStatement.bindBytes(PgPreparedStatement.java:1012)
    at org.postgresql.jdbc.PgPreparedStatement.setLong(PgPreparedStatement.java:302)
    at org.apache.commons.dbcp2.DelegatingPreparedStatement.setLong(DelegatingPreparedStatement.java:428)
    at org.apache.commons.dbcp2.DelegatingPreparedStatement.setLong(DelegatingPreparedStatement.java:428)
    at org.hibernate.type.descriptor.sql.BigIntTypeDescriptor$1.doBind(BigIntTypeDescriptor.java:46)
    at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:73)
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:276)
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:271)
    at org.hibernate.type.ComponentType.nullSafeSet(ComponentType.java:340)
    at org.hibernate.persister.entity.AbstractEntityPersister.dehydrateId(AbstractEntityPersister.java:2977)
    at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2935)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3226)
    ... 117 more

抱歉读了这么久。但我试图更详细地描述这个问题。如果有任何帮助,我将不胜感激。

dsf9zpds

dsf9zpds1#

你试过使用下列方法吗?

@Id
@Column(name = "asset_type_attribute_id", insertable = false, updatable = false)
private Long assetTypeAttributeId;

我认为您已经在id类中列出了这个属性,这可能会带来一个问题。
能否尝试将hibernate更新到最新版本5.4.24?如果问题仍然存在,请在问题跟踪器中创建问题(https://hibernate.atlassian.net)使用测试用例(https://github.com/hibernate/hibernate-test-case-templates/blob/master/orm/hibernate-orm-5/src/test/java/org/hibernate/bugs/jpaunittestcase.java)这再现了这个问题。

ffx8fchx

ffx8fchx2#

在吉拉发行-https://hibernate.atlassian.net/browse/hhh-14340. 似乎我找到了@embeddeble注解的解决方法。

@Entity
@Table(name = "asset")
public class Asset {

    @EmbeddedId
    private AssetId assetPK;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "id.asset", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<AssetAssetTypeAttribute> assetAssetTypeAttributes;

    /* getters, setters and etc... */
}

@Embeddable
public class AssetId implements Serializable {
    private Long id;
    @Column(name = "tenant_id")
    private Long tenantId;

    /* getters, setters and etc... */
}

@Entity
@Table(name = "asset_asset_type_attribute")
public class AssetAssetTypeAttribute {

    @EmbeddedId
    private AssetAttributeId id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "asset_type_attribute_id", referencedColumnName = "id", insertable = false, updatable = false)
    private AssetTypeAttribute assetTypeAttribute;

    private String value;

   /* getters, setters and etc... */
}

@Embeddable
public class AssetAttributeId implements Serializable {

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "asset_id", referencedColumnName = "id"),
            @JoinColumn(name = "tenant_id", referencedColumnName = "tenant_id"),
    })
    private Asset asset;
    private Long assetTypeAttributeId;

    /* getters, setters and etc... */
}

相关问题