【发布时间】:2021-12-11 15:05:18
【问题描述】:
在我的 spring-boot 项目中,我使用 spring-data、Hibernate 和 Oracle 作为数据库。
我有实体Message、User 和SeenMessage。
Messaage 看起来像:
@Entity
@Table(name = "MESSAGES")
public class Messages {
@Id
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MARKET_MESSAGE_GENERATOR")
@SequenceGenerator(name = "MARKET_MESSAGE_GENERATOR", sequenceName = "MARKET_MESSAGE_SEQ", allocationSize = 1)
private Long id;
@Basic
@Column(name = "PUBLISH_DATE")
private Timestamp dateTime;
@Basic
@Column(name = "TITLE")
private String title;
@Lob
@Nationalized
@Column(name = "MESSAGE", columnDefinition="NCLOB NOT NULL")
private String message;
}
User 看起来像:
@Entity
@Table(name = "Users")
public class User {
@Id
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_GENERATOR")
@SequenceGenerator(name = "USER_GENERATOR", sequenceName = "USERS_SEQ", allocationSize = 1)
private Long id;
@Basic
@Column(name = "USER_NAME")
private String userName;
}
而SeenMessage 看起来像:
@Entity
@Table(name = "SEEN_MESSAGE")
public class SeenMessage {
@Id
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEEN_MESSAGE_GENERATOR")
@SequenceGenerator(name = "SEEN_MESSAGE_GENERATOR", sequenceName = "SEEN_MESSAGE_SEQ", allocationSize = 1)
private Long id;
@Basic
@Column(name = "SEEN_DATE")
private Timestamp seenDate;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "MESSAGE_ID")
private Messages message;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "USER_ID")
private User user;
}
也在这张表上 (SEEN_MESSAGE) 我对一对 (Message_Id, User_Id) 有唯一的约束条件
现在的问题是:
我有一个简单的 REST API 用于获取带有其 ID 的消息,当有人调用此服务时,我将返回请求的消息,并且我将在 seenMessage 表中插入一条记录,其中包含 messageId 和 userId,当然还有是时候了。
我通过调用存储库中的方法在我的服务层中执行第二个操作(在 SeenMessage 中插入):
@Repository
public interface SeenMessageRepository extends JpaRepository<SeenMessage, Long> {
@Query(value = "begin " +
"insert into SEEN_MESSAGE(ID, MESSAGE_ID, USER_ID, SEEN_DATE) " +
"values(seen_message_seq.nextval, :MId , :UId , CURRENT_TIMESTAMP ); " +
"exception " +
"when dup_val_on_index THEN " +
"RETURN; " +
"end;", nativeQuery = true)
void insertAndForget(Long MId, Long UId);
}
如您所见,我编写了一个本机查询,当我在 DBMS 上执行它时,它会成功执行,但是当我使用 Postman 调用我的 API 时,查询将按我的预期执行和执行,但它也会引发异常是:
2021-10-26 11:12:50.385 ERROR 4848 --- [nio-1201-exec-2] c.a.b.o.exceptions.ExceptionTranslator : -1
java.lang.NegativeArraySizeException: -1
at org.hibernate.loader.custom.ResultRowProcessor.prepareForAutoDiscovery(ResultRowProcessor.java:36)
at org.hibernate.loader.custom.CustomLoader.autoDiscoverTypes(CustomLoader.java:489)
at org.hibernate.loader.Loader.preprocessResultSet(Loader.java:2343)
at org.hibernate.loader.Loader.getResultSet(Loader.java:2299)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2050)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2012)
at org.hibernate.loader.Loader.doQuery(Loader.java:948)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349)
at org.hibernate.loader.Loader.doList(Loader.java:2843)
at org.hibernate.loader.Loader.doList(Loader.java:2825)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2657)
at org.hibernate.loader.Loader.list(Loader.java:2652)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:338)
at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2141)
at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:1169)
at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:176)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1604)
at org.hibernate.query.internal.AbstractProducedQuery.getSingleResult(AbstractProducedQuery.java:1652)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:196)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:88)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:155)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:143)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:159)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:138)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:145)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
at com.sun.proxy.$Proxy125.insertAndForget(Unknown Source)
也许可以说我写了这个查询并且没有使用简单的插入查询,因为在这种情况下我需要自己检查重复(如果我没有检查重复我可能会遇到UniqueconstraintViolationException)另一个我认为额外的数据库调用,所以我写了这个。
谁能告诉我这个错误的原因??
为什么它在 DBMS 上执行没有错误,但在我的应用程序中却导致错误??
任何帮助将不胜感激!
【问题讨论】:
标签: java oracle spring-boot hibernate spring-data-jpa