org.springframework.dao.InvalidDataAccessApiUsageException:参数值与预期类型 java.time.LocalDateTime 不匹配

Posted

技术标签:

【中文标题】org.springframework.dao.InvalidDataAccessApiUsageException:参数值与预期类型 java.time.LocalDateTime 不匹配【英文标题】:org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value did not match expected type java.time.LocalDateTime 【发布时间】:2018-09-02 15:24:10 【问题描述】:

我刚刚开始处理其他人开发的代码。它是基于规范模式使用 Spring Data 和 Hibernate 设计的。

简而言之,如果我尝试使用字符串、布尔值或整数字段进行搜索,它可以正常工作。例如,当我使用 state==SP 搜索/过滤时,我得到了结果,我可以看到硅藻土字段已正确填写。我还看到 hibernate 在这种情况下没有抱怨无效数据:

当我使用“state==SP”成功搜索时从我的控制台复制 ... TRACE 2450 --- [nio-9000-exec-2] o.h.type.descriptor.sql.BasicExtractor:提取值([created17_12_]:[TIMESTAMP])-[2013-07-12T06:53:47] ...

尽管如此,当我使用 datetime 搜索/过滤时,我得到了这个问题中总结的错误。例如:我搜索“createdDate==2014-06-03T18:48:33”,我得到:

2018-03-23 17:38:17.547 ERROR 2450 --- [nio-9000-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [2014-06-03T18:48:33] did not match expected type [java.time.LocalDateTime (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [2014-06-03T18:48:33] did not match expected type [java.time.LocalDateTime (n/a)]] with root cause

java.lang.IllegalArgumentException: Parameter value [2014-06-03T18:48:33] did not match expected type [java.time.LocalDateTime (n/a)]
    at org.hibernate.jpa.spi.BaseQueryImpl.validateBinding(BaseQueryImpl.java:897) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.internal.QueryImpl.access$000(QueryImpl.java:61) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.internal.QueryImpl$ParameterRegistrationImpl.bindValue(QueryImpl.java:235) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.spi.BaseQueryImpl.setParameter(BaseQueryImpl.java:638) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.spi.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:163) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.spi.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:32) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.criteria.compile.CriteriaCompiler$1$1.bind(CriteriaCompiler.java:109) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.criteria.CriteriaQueryImpl$1.buildCompiledQuery(CriteriaQueryImpl.java:366) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.criteria.compile.CriteriaCompiler.compile(CriteriaCompiler.java:130) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:699) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at sun.reflect.GeneratedMethodAccessor93.invoke(Unknown Source) ~[na:na]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_162]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_162]
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:347) ~[spring-orm-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at com.sun.proxy.$Proxy115.createQuery(Unknown Source) ~[na:na]
    at sun.reflect.GeneratedMethodAccessor93.invoke(Unknown Source) ~[na:na]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_162]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_162]
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298) ~[spring-orm-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at com.sun.proxy.$Proxy115.createQuery(Unknown Source) ~[na:na]
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:656) ~[spring-data-jpa-1.11.6.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:608) ~[spring-data-jpa-1.11.6.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:407) ~[spring-data-jpa-1.11.6.RELEASE.jar:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_162]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_162]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_162]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_162]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:504) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:489) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:461) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:56) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133) ~[spring-data-jpa-1.11.6.RELEASE.jar:na]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at com.sun.proxy.$Proxy150.findAll(Unknown Source) ~[na:na]
    at br.com.moving.service.ApiServiceImpl.list(ApiServiceImpl.java:48)

调用 findAll 时存储库引发错误:

@Repository
@Transactional
public class ApiServiceImpl implements ApiService 

    @PersistenceContext
    private EntityManager em;

    @Override
    public <T> Page<T> list(Class<T> clazz, Class<? extends JpaSpecificationExecutor<T>> clazz2, String search,
            Pageable pageable, Class<? extends Specification<T>> specClazz) 
        JpaSpecificationExecutor<T> repository = new JpaRepositoryFactory(em).getRepository(clazz2);

        SpecificationBuilder<T> builder = new SpecificationBuilder<>(specClazz);
        Pattern pattern = Pattern.compile("(\\w+.*?)(==|!=|<|<=|>|>=|=|===)((\\*|\\w+).*?);");
        Matcher matcher = pattern.matcher(search + ";");
        while (matcher.find()) 
            builder.with(matcher.group(1), matcher.group(2), matcher.group(3));
        

        org.springframework.data.jpa.domain.Specification<T> spec = builder.build();
        Page<T> page = repository.findAll(spec, pageable);

        return page;
    
...

ApiService 接口

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

import br.com.mycompany.specification.Specification;

public interface ApiService 

    <T> Page<T> list(Class<T> clazz, Class<? extends JpaSpecificationExecutor<T>> clazz2, String search, Pageable pageable, Class<? extends Specification<T>> customSpec);

    <T> T get(Class<T> clazz, Class<? extends JpaSpecificationExecutor<T>> clazz2, String search, Class<? extends Specification<T>> customSpec);

LocalDateTimeSerializer:

    import java.io.IOException;
    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;

    import com.fasterxml.jackson.core.JsonGenerator;
    import com.fasterxml.jackson.databind.JsonSerializer;

    public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> 

        @Override
        public void serialize(LocalDateTime dateTime, JsonGenerator generator,
                com.fasterxml.jackson.databind.SerializerProvider provider)
                throws IOException, com.fasterxml.jackson.core.JsonProcessingException 
            if (dateTime == null) 
                generator.writeNull();
             else 
                generator.writeString(dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")));
            
        


型号:

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import br.com.mycompany.converter.BooleanNumberConverter;
import br.com.mycompany.converter.ReleaseCategoryTypeConverter;
import br.com.mycompany.converter.ReleaseStatusTypeConverter;
import br.com.mycompany.serializer.LocalDateTimeSerializer;


@Entity
@Table(name = "releases")
@JsonInclude(Include.NON_NULL)
public class Release implements Serializable 

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Long id;

    @Column(name = "state", length = 2)
    private String state;

    @JsonSerialize(using = LocalDateTimeSerializer.class)
    @Column(name = "created_date", nullable = false, insertable = true, updatable = false)
    private LocalDateTime createdDate = LocalDateTime.now();

//other fields, constructors, gets/sets not relevant

数据库是mysql。如果我通过 Workbench 在 MySql 中搜索 straigh,我可以看到这个示例:

select created_date from releases

'0000-00-00 00:00:00'
'0000-00-00 00:00:00'
...
'2013-09-28 09:19:23'
'2013-09-28 09:19:59'

通过锁定关闭格式,在我看来 LocalDateTimeSerializer.serialize 是正确的。

任何线索将不胜感激。

****已编辑

仔细阅读Hibernate 4 with java.time.LocalDate and DATE() construct后,我检查了我有哪些jar版本,据我所知,如果我的jar有问题,我没有找到任何提示。我在两个打印屏幕下方添加了显示我正在使用的 jar 版本。 此外,我将在下面粘贴使用的三种方法。这三个都导致了上述相同的错误。

图书馆:

使用的方法完全没有区别:

1 - 从列中删除了 @JsonSerialize 和 @Converter。我的意思是:

//@JsonSerialize(using = LocalDateTimeSerializer.class)
//@Convert(converter = MovingLocalDateTimeConverter.class)
@Column(name = "created_date", nullable = false, insertable = true, updatable = false)
private LocalDateTime createdDate;

2 - 添加了 JsonSerialize。我的意思是:

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;

public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> 

    @Override
    public void serialize(LocalDateTime dateTime, JsonGenerator generator,
            com.fasterxml.jackson.databind.SerializerProvider provider)
            throws IOException, com.fasterxml.jackson.core.JsonProcessingException 
        if (dateTime == null) 
            generator.writeNull();
         else 
            generator.writeString(dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")));
        
    


@JsonSerialize(using = LocalDateTimeSerializer.class)
@Column(name = "created_date", nullable = false, insertable = true, updatable = false)
private LocalDateTime createdDate;

3 - 添加了转换器。我的意思是,

import java.time.DateTimeException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter
public class MovingLocalDateTimeConverter implements AttributeConverter<LocalDateTime, String> 

    //private DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");

    @Override
    public String convertToDatabaseColumn(LocalDateTime value) 
        return (value != null) ? value.format(fmt) : null;
    

    @Override
    public LocalDateTime convertToEntityAttribute(String value) 
        return convertLocalDateTime(value);
    

    private LocalDateTime convertLocalDateTime(String value) 
        try 
            return (value != null) ? LocalDateTime.parse(value.substring(0, 19), fmt) : null;
         catch (DateTimeException e) 
            return null;
        
    


@Convert(converter = MovingLocalDateTimeConverter.class)
@Column(name = "created_date", nullable = false, insertable = true, updatable = false)
private LocalDateTime createdDate;

当前错误完全没有改变所有暂定值。

【问题讨论】:

我也遇到了同样的问题,你解决了吗?如果是这样,你能分享一下解决方案吗? 【参考方案1】:

我建议您添加以下依赖项。更多信息请参考here

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-java8</artifactId>
    <version>$hibernate.version</version>
</dependency>

【讨论】:

没有任何改变。我仍然收到“java.lang.IllegalArgumentException:参数值 [2014-06-03T18:48:33] 与 org.hibernate.jpa.spi 的预期类型 [java.time.LocalDateTime (n/a)] 不匹配。 BaseQueryImpl.validateBinding(BaseQueryImpl.java:897) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final] at org.hibernate.jpa.internal.QueryImpl.access$000(QueryImpl.java:61) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]" 你删除了你的LocalDateTimeSerializer吗? 是的,我从所有 java.time.LocalDateTime 中删除了它(我有三个字段)。我仍然得到完全相同的错误。我正在仔细阅读***.com/questions/23890687/…,但我看不出我能做什么。另外,有趣的是,这个问题没有选择答案。

以上是关于org.springframework.dao.InvalidDataAccessApiUsageException:参数值与预期类型 java.time.LocalDateTime 不匹配的主要内容,如果未能解决你的问题,请参考以下文章