Spring Data Cassandra:InvalidQueryException:UUID应该为16或0个字节(20)

时间:2018-06-26 06:43:54

标签: java cassandra spring-data-cassandra

实体

@Builder
@Getter @Setter
@ToString(doNotUseGetters = true)
@EqualsAndHashCode(doNotUseGetters = true)
@Table(value = "entity")
public class Entity implements Serializable {

    @PrimaryKeyColumn(name = "id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
    @CassandraType(type = DataType.Name.UUID)
    private UUID Id;

    @Column("list_name")
    @CassandraType(type = DataType.Name.TEXT)
    private String name;

    @Column("type")
    @CassandraType(type = DataType.Name.TINYINT)
    private Byte type;

实体回购

@Repository
public interface EntityRepo extends BaseRepo<Entity, UUID> {

    @Query("SELECT * FROM entity WHERE id IN (:id)")
    Collection<ListEntity> findByIds(@Param("id") Collection<UUID> listIds);

    @Query("SELECT * FROM entity WHERE list_id = :id")
    ListEntity findById(@Param("id") UUID id);

}  

查询

listRepo.findByListId(UUIDs.random())
listRepo.findByListIds(Arrays.asList(UUIDs.random())

两者都会导致

CassandraInvalidQueryException/InvalidQueryException
org.springframework.data.cassandra.CassandraInvalidQueryException: Query; CQL 
[SELECT * FROM lists WHERE list_id IN (?)]; UUID should be 16 or 0 bytes (20); 
nested exception is com.datastax.driver.core.exceptions.`InvalidQueryException: UUID should be 16 or 0 bytes (20)

这里缺少什么?有人可以帮忙吗?

3 个答案:

答案 0 :(得分:0)

通过将集合传递到单个绑定值中,似乎无法使用UUID进行IN查询。

这是发生的情况:

Spring Data转换您的字符串查询

SELECT * FROM entity WHERE id IN (:id)

使用位置查询参数进入Cassandra的表示法

SELECT * FROM entity WHERE id IN (?)

并将给定参数绑定到?。让我们将其转换为可执行代码:

session.execute(new SimpleStatement("SELECT * FROM entity WHERE id IN (?)",
                                     Arrays.asList(UUIDs.random())));

运行此片段后,您将再次以InvalidQueryException结尾。我们仍然可以进行IN查询,但是我们需要展开参数:

new SimpleStatement("SELECT * FROM entity WHERE id IN (?, ?)", UUIDs.random(), UUIDs.random())

在理想情况下,Cassandra可以接受List(或Set)项,以使查询字符串与实际参数个数无关。

答案 1 :(得分:0)

这是我的工作。

使用: findAllBy [object-property] In ,其中[object-property]是MyModel UUID的属性名称。

@Table("example")
public class MyModel {
    @PrimaryKeyColumn(name = "uuid", type = PrimaryKeyType.PARTITIONED)
    private UUID uuid;

    @Column("...")
    ...
}

public interface MyRepository extends CassandraRepository<MyModel, UUID> {
    List<Restaurant> findAllByUuidIn(Collection<UUID> uuidButIfYouWant);
}

// It is OK
return this.myRepository.findAllByUuidIn(Set.of(
    UUID.randomUUID(),
    UUID.randomUUID()
));

// Throw Error: no viable alternative at input '<EOF>' (SELECT * FROM example WHERE [uuid] IN...)
return this.myRepository.findAllByUuidIn(Set.of());

因此,如果不包含uuid:

Collection<UUID> search = Set.of();

if(search.size() == 0) {
    return List.of();
}

return this.myRepository.findAllByUuidIn(search);

答案 2 :(得分:0)

(我正在添加此答案以供将来参考)

我在运行 spark 应用程序时遇到了同样的错误。

在执行 Cassandra 查询时发生错误,并且在需要 UUID 类型的地方,查询发送了一些其他数据类型。就我而言,它是一个字符串。传递正确的数据类型(UUID 而不是 String)解决了这个问题。