Spring & Couchbase - 找不到能够从类型 [java.lang.Long] 转换为类型 [java.sql.Timestamp] 的转换器
Spring & Couchbase - No converter found capable of converting from type [java.lang.Long] to type [java.sql.Timestamp]
我们有一份文档保存到 Couchbase 数据库中。它有一个时间戳字段:
@Document
class Cat{
@Id
@GeneratedValue(strategy = GenerationStrategy.UNIQUE)
private String id;
@Field
Timestamp birthdateTimestamp;
我们可以在创建 Cat 时将数据保存到字段中:
Timestamp currentTimestamp = new Timestamp(new Date().getTime());
Cat cat = Cat.builder().birthdateTimestamp(currentTimestamp).build();
catRepository.save(cat); // extends CouchbaseRepository<Cat, String>
并且可以在数据库中正确看到该字段 - "birthdateTimestamp": 1564570366644
但是,当尝试从数据库中读取 Cat
时,我们收到此错误:
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.Long] to type [java.sql.Timestamp]] with root cause
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.Long] to type [java.sql.Timestamp]
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:321)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:194)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174)
at org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter.readValue(MappingCouchbaseConverter.java:804)
at org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter.access0(MappingCouchbaseConverter.java:77)
at org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter$CouchbasePropertyValueProvider.getPropertyValue(MappingCouchbaseConverter.java:869)
at org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter$CouchbasePropertyValueProvider.getPropertyValue(MappingCouchbaseConverter.java:824)
at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:71)
at org.springframework.data.mapping.model.SpELExpressionParameterValueProvider.getParameterValue(SpELExpressionParameterValueProvider.java:49)
at org.springframework.data.convert.ClassGeneratingEntityInstantiator$EntityInstantiatorAdapter.extractInvocationArguments(ClassGeneratingEntityInstantiator.java:248)
at org.springframework.data.convert.ClassGeneratingEntityInstantiator$EntityInstantiatorAdapter.createInstance(ClassGeneratingEntityInstantiator.java:221)
at org.springframework.data.convert.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:86)
at org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter.read(MappingCouchbaseConverter.java:236)
at org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter.read(MappingCouchbaseConverter.java:213)
at org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter.read(MappingCouchbaseConverter.java:171)
at org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter.read(MappingCouchbaseConverter.java:77)
at org.springframework.data.couchbase.core.CouchbaseTemplate.mapToEntity(CouchbaseTemplate.java:700)
at org.springframework.data.couchbase.core.CouchbaseTemplate.findByN1QL(CouchbaseTemplate.java:448)
at org.springframework.data.couchbase.repository.query.AbstractN1qlBasedQuery.executeCollection(AbstractN1qlBasedQuery.java:156)
at org.springframework.data.couchbase.repository.query.AbstractN1qlBasedQuery.executeEntity(AbstractN1qlBasedQuery.java:162)
at org.springframework.data.couchbase.repository.query.AbstractN1qlBasedQuery.executeDependingOnType(AbstractN1qlBasedQuery.java:135)
at org.springframework.data.couchbase.repository.query.AbstractN1qlBasedQuery.execute(AbstractN1qlBasedQuery.java:106)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:590)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:578)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.couchbase.repository.support.ViewPostProcessor$ViewInterceptor.invoke(ViewPostProcessor.java:87)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy130.findByCustomerNameAndProjectName(Unknown Source)
我们做错了什么?
看起来该值正在以 Epoch 格式存储在数据库中。
与其尝试将纪元直接转换为 sql 时间戳,不如将其存储为 long,即
@Field
long birthdateTimestamp;
然后要从纪元格式转换为 sql 时间戳,您可以使用类似以下内容。
new Timestamp(object.getBirthdateTimestamp())
我们有一份文档保存到 Couchbase 数据库中。它有一个时间戳字段:
@Document
class Cat{
@Id
@GeneratedValue(strategy = GenerationStrategy.UNIQUE)
private String id;
@Field
Timestamp birthdateTimestamp;
我们可以在创建 Cat 时将数据保存到字段中:
Timestamp currentTimestamp = new Timestamp(new Date().getTime());
Cat cat = Cat.builder().birthdateTimestamp(currentTimestamp).build();
catRepository.save(cat); // extends CouchbaseRepository<Cat, String>
并且可以在数据库中正确看到该字段 - "birthdateTimestamp": 1564570366644
但是,当尝试从数据库中读取 Cat
时,我们收到此错误:
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.Long] to type [java.sql.Timestamp]] with root cause org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.Long] to type [java.sql.Timestamp] at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:321) at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:194) at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174) at org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter.readValue(MappingCouchbaseConverter.java:804) at org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter.access0(MappingCouchbaseConverter.java:77) at org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter$CouchbasePropertyValueProvider.getPropertyValue(MappingCouchbaseConverter.java:869) at org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter$CouchbasePropertyValueProvider.getPropertyValue(MappingCouchbaseConverter.java:824) at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:71) at org.springframework.data.mapping.model.SpELExpressionParameterValueProvider.getParameterValue(SpELExpressionParameterValueProvider.java:49) at org.springframework.data.convert.ClassGeneratingEntityInstantiator$EntityInstantiatorAdapter.extractInvocationArguments(ClassGeneratingEntityInstantiator.java:248) at org.springframework.data.convert.ClassGeneratingEntityInstantiator$EntityInstantiatorAdapter.createInstance(ClassGeneratingEntityInstantiator.java:221) at org.springframework.data.convert.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:86) at org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter.read(MappingCouchbaseConverter.java:236) at org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter.read(MappingCouchbaseConverter.java:213) at org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter.read(MappingCouchbaseConverter.java:171) at org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter.read(MappingCouchbaseConverter.java:77) at org.springframework.data.couchbase.core.CouchbaseTemplate.mapToEntity(CouchbaseTemplate.java:700) at org.springframework.data.couchbase.core.CouchbaseTemplate.findByN1QL(CouchbaseTemplate.java:448) at org.springframework.data.couchbase.repository.query.AbstractN1qlBasedQuery.executeCollection(AbstractN1qlBasedQuery.java:156) at org.springframework.data.couchbase.repository.query.AbstractN1qlBasedQuery.executeEntity(AbstractN1qlBasedQuery.java:162) at org.springframework.data.couchbase.repository.query.AbstractN1qlBasedQuery.executeDependingOnType(AbstractN1qlBasedQuery.java:135) at org.springframework.data.couchbase.repository.query.AbstractN1qlBasedQuery.execute(AbstractN1qlBasedQuery.java:106) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:590) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:578) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.data.couchbase.repository.support.ViewPostProcessor$ViewInterceptor.invoke(ViewPostProcessor.java:87) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy130.findByCustomerNameAndProjectName(Unknown Source)
我们做错了什么?
看起来该值正在以 Epoch 格式存储在数据库中。
与其尝试将纪元直接转换为 sql 时间戳,不如将其存储为 long,即
@Field
long birthdateTimestamp;
然后要从纪元格式转换为 sql 时间戳,您可以使用类似以下内容。
new Timestamp(object.getBirthdateTimestamp())