从 Hibernate 5 迁移到 6

bar*_*ssa 1 hibernate-5.x hibernate-6.x java-17

我正在尝试将在 java 8 上运行的 spring boot 2.3 应用程序迁移到 spring boot 3 java 17。问题出在存储库中。

其查询方法如下:

@Query(value = "SELECT ca FROM CorporateActionsV2 ca WHERE ( ca.dividendAmount, TO_CHAR(TO_DATE(ca.effectiveDate) - 5,'IYYY'), TO_CHAR(TO_DATE(ca.effectiveDate) - 5,'IW'), ca.tickerSerial) IN (SELECT c.dividendAmount, TO_CHAR(TO_DATE(c.effectiveDate) - 5,'IYYY'), TO_CHAR(TO_DATE(c.effectiveDate) - 5,'IW'), c.tickerSerial FROM CorporateActionsV2 c WHERE c.dividendAmount IS NOT NULL AND c.eventLabel = 'Dividend' AND c.actionStatus != 'Deleted'" +
        " GROUP BY c.dividendAmount, TO_CHAR(TO_DATE(c.effectiveDate) - 5,'IYYY'), TO_CHAR(TO_DATE(c.effectiveDate) - 5,'IW'), c.tickerSerial HAVING COUNT(*) > 1 )")
List<CorporateActionsV2> getDuplicateActions();
Run Code Online (Sandbox Code Playgroud)

该实体CorporateActionsV2具有以下日期结构:

@Temporal(TemporalType.DATE)
@Column(name = "EFFECTIVE_DATE")
@JsonProperty("EFFECTIVE_DATE")
private Date effectiveDate;
Run Code Online (Sandbox Code Playgroud)

当 Spring Boot 启动时,出现以下异常:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'corporateActionV2Service' defined in file [D:\company\content_contribution_platform\application\target\classes\com\mubasher\ccp\services\CorporateActionV2Service.class]: Unsatisfied dependency expressed through constructor parameter 1: Error creating bean with name 'corporateActionV2Repository' defined in com.mubasher.ccp.repositories.ms.history.CorporateActionV2Repository defined in @EnableJpaRepositories declared on MSHistoryConfig: Could not create query for public abstract java.util.List com.mubasher.ccp.repositories.ms.history.CorporateActionV2Repository.getDuplicateActions(); Reason: Validation failed for query for method public abstract java.util.List com.mubasher.ccp.repositories.ms.history.CorporateActionV2Repository.getDuplicateActions()
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:793)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:242)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1344)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1188)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:961)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:915)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291)
    at com.mubasher.ccp.Application.main(Application.java:29)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'corporateActionV2Repository' defined in com.mubasher.ccp.repositories.ms.history.CorporateActionV2Repository defined in @EnableJpaRepositories declared on MSHistoryConfig: Could not create query for public abstract java.util.List com.mubasher.ccp.repositories.ms.history.CorporateActionV2Repository.getDuplicateActions(); Reason: Validation failed for query for method public abstract java.util.List com.mubasher.ccp.repositories.ms.history.CorporateActionV2Repository.getDuplicateActions()
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1751)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1405)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1325)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:880)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:784)
    ... 24 common frames omitted
Caused by: org.springframework.data.repository.query.QueryCreationException: Could not create query for public abstract java.util.List com.mubasher.ccp.repositories.ms.history.CorporateActionV2Repository.getDuplicateActions(); Reason: Validation failed for query for method public abstract java.util.List com.mubasher.ccp.repositories.ms.history.CorporateActionV2Repository.getDuplicateActions()
    at org.springframework.data.repository.query.QueryCreationException.create(QueryCreationException.java:101)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lookupQuery(QueryExecutorMethodInterceptor.java:115)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.mapMethodsToQuery(QueryExecutorMethodInterceptor.java:99)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lambda$new$0(QueryExecutorMethodInterceptor.java:88)
    at java.base/java.util.Optional.map(Optional.java:260)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.<init>(QueryExecutorMethodInterceptor.java:88)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:357)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:279)
    at org.springframework.data.util.Lazy.getNullable(Lazy.java:229)
    at org.springframework.data.util.Lazy.get(Lazy.java:113)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:285)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:132)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1797)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1747)
    ... 35 common frames omitted
Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List com.mubasher.ccp.repositories.ms.history.CorporateActionV2Repository.getDuplicateActions()
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:100)
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.<init>(SimpleJpaQuery.java:70)
    at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromMethodWithQueryString(JpaQueryFactory.java:55)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$DeclaredQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:170)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:252)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:95)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lookupQuery(QueryExecutorMethodInterceptor.java:111)
    ... 47 common frames omitted
Caused by: java.lang.IllegalArgumentException: org.hibernate.QueryException: Parameter 1 of function to_date() has type STRING, but argument is of type java.util.Date
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:141)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:175)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:182)
    at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:761)
    at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:663)
    at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:127)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:360)
    at jdk.proxy3/jdk.proxy3.$Proxy139.createQuery(Unknown Source)
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:94)
    ... 53 common frames omitted
Caused by: org.hibernate.QueryException: Parameter 1 of function to_date() has type STRING, but argument is of type java.util.Date
    at org.hibernate.query.sqm.produce.function.ArgumentTypesValidator.throwError(ArgumentTypesValidator.java:214)
    at org.hibernate.query.sqm.produce.function.ArgumentTypesValidator.checkType(ArgumentTypesValidator.java:169)
    at org.hibernate.query.sqm.produce.function.ArgumentTypesValidator.validate(ArgumentTypesValidator.java:74)
    at org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor.generateSqmExpression(AbstractSqmFunctionDescriptor.java:104)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitGenericFunction(SemanticQueryBuilder.java:3664)
    at org.hibernate.grammars.hql.HqlParser$GenericFunctionContext.accept(HqlParser.java:10209)
    at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visitChildren(AbstractParseTreeVisitor.java:46)
    at org.hibernate.grammars.hql.HqlParserBaseVisitor.visitFunction(HqlParserBaseVisitor.java:1112)
    at org.hibernate.grammars.hql.HqlParser$FunctionContext.accept(HqlParser.java:9977)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitFunctionExpression(SemanticQueryBuilder.java:1432)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitFunctionExpression(SemanticQueryBuilder.java:243)
    at org.hibernate.grammars.hql.HqlParser$FunctionExpressionContext.accept(HqlParser.java:6849)
    at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visitChildren(AbstractParseTreeVisitor.java:46)
    at org.hibernate.grammars.hql.HqlParserBaseVisitor.visitBarePrimaryExpression(HqlParserBaseVisitor.java:671)
    at org.hibernate.grammars.hql.HqlParser$BarePrimaryExpressionContext.accept(HqlParser.java:6437)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitAdditionExpression(SemanticQueryBuilder.java:2613)
    at org.hibernate.grammars.hql.HqlParser$AdditionExpressionContext.accept(HqlParser.java:6395)
    at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visitChildren(AbstractParseTreeVisitor.java:46)
    at org.hibernate.grammars.hql.HqlParserBaseVisitor.visitExpressionOrPredicate(HqlParserBaseVisitor.java:811)
    at org.hibernate.grammars.hql.HqlParser$ExpressionOrPredicateContext.accept(HqlParser.java:7186)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitGenericFunctionArguments(SemanticQueryBuilder.java:3781)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitGenericFunctionArguments(SemanticQueryBuilder.java:243)
    at org.hibernate.grammars.hql.HqlParser$GenericFunctionArgumentsContext.accept(HqlParser.java:10559)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitGenericFunction(SemanticQueryBuilder.java:3563)
    at org.hibernate.grammars.hql.HqlParser$GenericFunctionContext.accept(HqlParser.java:10209)
    at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visitChildren(AbstractParseTreeVisitor.java:46)
    at org.hibernate.grammars.hql.HqlParserBaseVisitor.visitFunction(HqlParserBaseVisitor.java:1112)
    at org.hibernate.grammars.hql.HqlParser$FunctionContext.accept(HqlParser.java:9977)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitFunctionExpression(SemanticQueryBuilder.java:1432)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitFunctionExpression(SemanticQueryBuilder.java:243)
    at org.hibernate.grammars.hql.HqlParser$FunctionExpressionContext.accept(HqlParser.java:6849)
    at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visitChildren(AbstractParseTreeVisitor.java:46)
    at org.hibernate.grammars.hql.HqlParserBaseVisitor.visitBarePrimaryExpression(HqlParserBaseVisitor.java:671)
    at org.hibernate.grammars.hql.HqlParser$BarePrimaryExpressionContext.accept(HqlParser.java:6437)
    at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visitChildren(AbstractParseTreeVisitor.java:46)
    at org.hibernate.grammars.hql.HqlParserBaseVisitor.visitExpressionOrPredicate(HqlParserBaseVisitor.java:811)
    at org.hibernate.grammars.hql.HqlParser$ExpressionOrPredicateContext.accept(HqlParser.java:7186)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitExpressions(SemanticQueryBuilder.java:2736)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitTupleExpression(SemanticQueryBuilder.java:2724)
    at org.hibernate.grammars.hql.HqlParser$TupleExpressionContext.accept(HqlParser.java:6465)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitInPredicate(SemanticQueryBuilder.java:2282)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitInPredicate(SemanticQueryBuilder.java:243)
    at org.hibernate.grammars.hql.HqlParser$InPredicateContext.accept(HqlParser.java:5466)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitWhereClause(SemanticQueryBuilder.java:1949)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitWhereClause(SemanticQueryBuilder.java:243)
    at org.hibernate.grammars.hql.HqlParser$WhereClauseContext.accept(HqlParser.java:5290)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitQuery(SemanticQueryBuilder.java:857)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitQuerySpecExpression(SemanticQueryBuilder.java:629)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitQuerySpecExpression(SemanticQueryBuilder.java:243)
    at org.hibernate.grammars.hql.HqlParser$QuerySpecExpressionContext.accept(HqlParser.java:1218)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSimpleQueryGroup(SemanticQueryBuilder.java:623)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSimpleQueryGroup(SemanticQueryBuilder.java:243)
    at org.hibernate.grammars.hql.HqlParser$SimpleQueryGroupContext.accept(HqlParser.java:1131)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSelectStatement(SemanticQueryBuilder.java:399)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitStatement(SemanticQueryBuilder.java:358)
    at org.hibernate.query.hql.internal.SemanticQueryBuilder.buildSemanticModel(SemanticQueryBuilder.java:285)
    at org.hibernate.query.hql.internal.StandardHqlTranslator.translate(StandardHqlTranslator.java:81)
    at org.hibernate.internal.AbstractSharedSessionContract.lambda$createQuery$2(AbstractSharedSessionContract.java:748)
    at org.hibernate.query.internal.QueryInterpretationCacheStandardImpl.createHqlInterpretation(QueryInterpretationCacheStandardImpl.java:141)
    at org.hibernate.query.internal.QueryInterpretationCacheStandardImpl.resolveHqlInterpretation(QueryInterpretationCacheStandardImpl.java:128)
    at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:745)
    ... 62 common frames omitted
Run Code Online (Sandbox Code Playgroud)

从 hibernate-5 到 hibernate-6 缺少什么?该代码在旧版本中运行良好,并且从文档来看,hibernate 5 和 6 之间没有太大区别。

Gav*_*ing 5

正如 Octavia Adler 正确回答的那样,将日期传递给函数是没有意义的to_date()

从 Hibernate 6 开始,HQL 函数的参数类型现在已进行类型检查,因此 Hibernate 将发现这种性质的错误并用合理的错误消息报告它们,在本例中:

org.hibernate.QueryException: Parameter 1 of function to_date() has type STRING, but argument is of type java.util.Date
Run Code Online (Sandbox Code Playgroud)

也许您错过了这条消息,因为 Spring 似乎将 Hibernate 中的有用异常包装在不只是一两个而是四个不同的无用异常中,这些异常无法保留根本原因的错误消息。

你应该向 Spring 开发人员抱怨这一点,因为在我看来,这在库设计方面是一种糟糕的做法。

  • 我怀疑这些异常是没有用的,因为它们将低级问题连接到应用程序代码中的问题根源,因此也是潜在解决问题的点。如果没有这些信息,检测该点就不会更容易。恰恰相反。 (2认同)
  • 话虽如此,确实有一关是可以废掉的。我已在[此处](https://github.com/spring-projects/spring-data-jpa/issues/2736)提交了一张票。我想可能值得注意的是,由于 Hibernate 3/4 代中的错误,必须引入特定的包装步骤,如[此处](https://download.oracle.com/javaee-archive/jpa 中记录的那样) -spec.java.net/user/2012/07/0404.html)。 (2认同)