无法在sqlite中保存UUID id为的聚合根

无法在sqlite中保存UUID id为的聚合根,sqlite,spring-data-jdbc,Sqlite,Spring Data Jdbc,在我的项目中,我有以下可以成功保存在Postgres中的实体: public class Aggregate { @Id private UUID id; private JsonNode data; // getters and setters omitted } 当我尝试在SQLite中保存相同的实体时,我得到以下异常: org.springframework.core.convert.ConverterNotFoundException: No converter

在我的项目中,我有以下可以成功保存在Postgres中的实体:

public class Aggregate {

  @Id
  private UUID id;

  private JsonNode data;

  // getters and setters omitted
}
当我尝试在SQLite中保存相同的实体时,我得到以下异常:

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.Integer] to type [java.util.UUID]
    at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:322) ~[spring-core-5.3.5.jar:5.3.5]
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:195) ~[spring-core-5.3.5.jar:5.3.5]
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:175) ~[spring-core-5.3.5.jar:5.3.5]
    at org.springframework.data.mapping.model.ConvertingPropertyAccessor.convertIfNecessary(ConvertingPropertyAccessor.java:120) ~[spring-data-commons-2.4.6.jar:2.4.6]
    at org.springframework.data.mapping.model.ConvertingPropertyAccessor.setProperty(ConvertingPropertyAccessor.java:63) ~[spring-data-commons-2.4.6.jar:2.4.6]
    at org.springframework.data.jdbc.core.JdbcAggregateChangeExecutionContext.setIdAndCascadingProperties(JdbcAggregateChangeExecutionContext.java:337) ~[spring-data-jdbc-2.1.6.jar:2.1.6]
    at org.springframework.data.jdbc.core.JdbcAggregateChangeExecutionContext.populateIdsIfNecessary(JdbcAggregateChangeExecutionContext.java:305) ~[spring-data-jdbc-2.1.6.jar:2.1.6]
    at org.springframework.data.jdbc.core.AggregateChangeExecutor.execute(AggregateChangeExecutor.java:52) ~[spring-data-jdbc-2.1.6.jar:2.1.6]
    at org.springframework.data.jdbc.core.JdbcAggregateTemplate.store(JdbcAggregateTemplate.java:339) ~[spring-data-jdbc-2.1.6.jar:2.1.6]
    at org.springframework.data.jdbc.core.JdbcAggregateTemplate.save(JdbcAggregateTemplate.java:149) ~[spring-data-jdbc-2.1.6.jar:2.1.6]
    at org.springframework.data.jdbc.repository.support.SimpleJdbcRepository.save(SimpleJdbcRepository.java:60) ~[spring-data-jdbc-2.1.6.jar:2.1.6]
SQLite的表定义:

create table aggregate
(
    id   text primary key,
    data text not null
);
出于某种原因,SpringDataJDBC试图在聚合中设置integer类型的id,尽管它是a)另一种类型,b)已经存在。我尝试了一个不同的
IdGenerator
,在表definiton中使用
而不使用rowid
,但没有任何变化

我使用的是Spring数据JDBC 2.1.6和xerial/sqlite JDBC 3.34.0

我怎样才能解决这个问题


更新以回答Jens Schauder的问题:我忘了提到适当设置UUID的回调。我还有两个转换器可以在
JsonNode
PGobject
之间进行转换(此处未显示)

@组件
公共类AggregateCallback在ConvertCallback之前实现{
@凌驾
转换前的公共骨料(最终骨料){
if(aggregate.getId()==null){
aggregate.setId(UUID.randomuid());
}
总回报;
}
}

不管数据库是什么,都会调用
聚合回调
,但是使用SQLite,在执行回调后会抛出异常。

切换到Jens Schauder在注释中建议的状态解决了问题

As@tammOr在修复问题后使用了一个版本进行了回答。 以下是原因和方式的解释

当Spring Data JDBC保存聚合时,它会在旧版本中执行以下操作:

  • 它确定聚合是否是新的。有多种方法可以做到这一点,但这里适用的情况是检查id是否为空(
    null
    用于对象类型,或
    0
    用于数字原语)

  • 由于id为
    null
    ,它决定聚合是新的,并且需要插入
    INSERT
    。在执行该操作之前,它会触发@tammOr用来设置id的一些事件

  • 然后执行插入

  • 由于默认策略是在数据库中生成id,因此它会在插入后尝试从JDBC驱动程序获取生成的id。出于某种原因,SQLite驱动程序实际上会返回一个类型为
    Integer
    的值

  • Spring数据JDBC然后尝试将其转换为
    UUID
    ,但失败了

  • 对于更高版本的SpringData,JDBC意识到在步骤4中它已经有了一个ID,并且没有向驱动程序请求生成的ID,因此跳过了步骤5,所以一切都很顺利


    这是解决问题的pull请求:

    您如何设置UUID?您所说的
    IdGenerator
    是什么意思?这在Spring数据JDBC中不是一个已知的概念。如前所述,这不适用于Postgres或任何其他数据库,因为没有生成id的内容,Spring数据JDBC会在保存后检查id是否已设置操作。@Jenschauder,我在问题中添加了相关部分。使用
    IdGenerator
    我指的是用我的自定义方言返回true的IdGenerator。您正在运行哪个版本?这可能在2.2 M5(2021.0.0)中得到修复如果没有,您是否有一个简单的github存储库,我可以看一下?我目前在2.1.6,将尝试上述版本。如果问题仍然存在,我将准备一个演示程序。因此,据我所知,您的问题是,当您从数据库中获取记录时,它会尝试为您的UUID分配一个整数值,对吗?非常感谢@Jenschauder的帮助:-)春季数据2021.0.0预计何时发布?目前计划在4月中旬发布。
    @Component
    public class AggregateCallback implements BeforeConvertCallback<Aggregate> {
    
      @Override
      public Aggregate onBeforeConvert(final Aggregate aggregate) {
        if (aggregate.getId() == null) {
          aggregate.setId(UUID.randomUUID());
        }
        return aggregate;
      }
    }