问题:处于聚合状态的axon springboot应用程序 @AggregateIdentifier
属于类型 UUID
postgresql数据库列的类型为 UUID
. 当在create命令上持久化时-标识符被成功存储。在发送更新命令时,警告会上升,并且命令不会传递到聚合处理程序,因为 @TargetAggregateIdentifier
这里需要axon描述的字符串类型:
java.lang.illegalargumentexception:为类…myaggregate提供了错误类型的id。应为:class java.util.uuid,get class java.lang.string
研究:
有效的解决方案是将域重构为 String
所有聚合标识符的类型。数据库 @Id
归档也应转换为 varchar(36)
要存储的类型 UUID.toString()
作为主键。主要的缺点是它效率低下:9倍大的大小和较慢的字符串读取。
最小的样板和折衷方案是将域重构为 String
所有骨料指示剂的类型和用途 javax.persistence.Converters
要在持久化时将jpa层中的字符串转换为uuid,请执行以下操作:
@Converter
public class UuidJpaConverter implements AttributeConverter<String, UUID> {
@Override
public UUID convertToDatabaseColumn(String uuid) {
return fromString(uuid);
}
@Override
public String convertToEntityAttribute(UUID uuid) {
return uuid.toString();
}
}
...
@Aggregate
@Entity
@IdClass(UuidKey.class)
public class MyAggregate implements Serializable {
@AggregateIdentifier
@Id
private String uuid;
...
}
public class UuidKey implements Serializable {
@Column(name = "uuid", nullable = false, updatable = false)
@Convert(converter = UuidJpaConverter.class)
private String uuid;
}
但结果是:
o、 h.engine.jdbc.spi.sqlexceptionhelper:错误:列“uuid”的类型为uuid,但表达式的类型为bytea
使用axon identifier converter,但它要求为每个聚合使用自定义genericjparepository,并且实际上从不在断点上调用identifierconverter处理程序:
@Configuration
public class IdentifierConverter {
@Bean
public GenericJpaRepository<MyAggregate> aggregateJpaRepository(
EntityManagerProvider provider,
@Qualifier("eventBus") EventBus simpleEventBus) {
GenericJpaRepository<MyAggregate> repository = GenericJpaRepository
.builder(MyAggregate.class)
-> .identifierConverter(name -> UUID.fromString(name))
.entityManagerProvider(provider)
.eventBus(simpleEventBus)
.build();
return repository;
}
}
结果是:
o、 h.engine.jdbc.spi.sqlexceptionhelper:错误:列“uuid”的类型为uuid,但表达式的类型为character variable
还有一个建议的通用genericjparepository解决方案,可以找到聚合标识符的类型,除非它已经是一个字符串,否则可以通过spring转换服务转换它。但目前还不清楚该将其绑定到何处 registerAggregateBeanDefinitions
在configurer中,当我们有axon自动配置并且bean被期望支持configurer时:
final Class<?> aggregateIdentifierType = Stream.of( aggregateType.getDeclaredFields( ) )
.filter( field -> field.isAnnotationPresent( AggregateIdentifier.class ) )
.map( field -> field.getType( ) )
.findFirst( )
.orElseThrow( ( ) -> new IllegalStateException( "The aggregate '" + aggregate + "' does not have an identifier." ) );
aggregateConf.configureRepository(
c -> GenericJpaRepository.builder( aggregateType )
.identifierConverter( string -> {
if ( aggregateType == String.class ) {
return string;
} else {
try {
final ConversionService conversionService = beanFactory.getBean( ConversionService.class );
return conversionService.convert( string, aggregateIdentifierType );
} catch ( final NoSuchBeanDefinitionException ex ) {
throw new IllegalStateException( "Unable to convert String to aggregate identifier of type '" + aggregateIdentifierType.getName( ) + "'. A conversion service is missing." );
}
}
} )
...
@Named
final class MyIdConverter implements Converter<String, MyId> {
...
@Override
public MyId convert( final String source ) {
return MyId.fromString( source );
}
}
问题:如何在postgresql数据库中保留聚合标识符的uuid类型 UUID
作为首选类型 @AggregateIdentifier
或者至少 String
. 也为什么只是 String
如果在2010年uuid在axon中被广泛使用,那么目前是否支持?
1条答案
按热度按时间4ioopgfo1#
老实说,你在这里对这件事做得很深入。我不确定是否能充分帮助你,但无论如何我都会试一试。
研究点1显然是让事情立即运转的最务实的解决方案。如果你要注意到
String
相比UUID
是我很难接受的。所以如果这是绝对的不,调查应该继续。否则,它当然会完成任务。说到第2点和第3点的研究,我相信您遇到了postgresql使用方言的问题,尽管我不是100%确定。尤其是postgresql提供了一些“很棒”的类型,但这些类型并不总是在所有场景中自动工作。我的“猜测”是基于强迫postgresql使用
BYTEA
而不是OID
如果你想的话,你应该降低博士后的吐司能力。如果您选择在事件存储中使用postgres,并且希望能够实际看到事件的内容,那么这将变得特别方便。这个博客文章举例说明了如何处理这个问题。更重要的是,这篇博文展示了如何调整所使用的方言。也许这能为你提供解决方案2和3?在这种情况下,选择4应该是最合理的解决方案。但我从你的React中得知,你目前还没有成功。当轴突和Spring结合时
SpringAxonAutoConfigurer
(您指的是registerAggregateBeanDefinitions
方法)将自动检查聚合上的可配置bean。它是基于@Aggregate
(即axon的spring原型注解)。更具体地说,您可以使用repository
中的字段@Aggregate
定义要使用的存储库的bean名称。因此,您应该能够简单地提供
GenericJpaRepository
用想要的豆子identifierConverter
. 该bean的名称不能在@Aggregate
在您的MyAggregate
,以便axon的自动配置可以正确地获取它。希望这对你有帮助!