Sanjay K S
Sanjay K S

Reputation: 305

Spring Data Cassandra: InvalidQueryException: UUID should be 16 or 0 bytes (20)

Entity

@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;

Entity Repo

@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);

}  

Query

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

Both results in

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)

Anything missing here? Can somebody help?

Upvotes: 1

Views: 3099

Answers (4)

Luciana Oliveira
Luciana Oliveira

Reputation: 1147

I hope you found an answer, but if you are using UUID version 4, maybe the type in your table are wrong. For example instead of UUID your ID field could be varchar.

Upvotes: 1

Tcheutchoua Steve
Tcheutchoua Steve

Reputation: 556

(I am adding this answer for future reference)

I had the same error when running a spark application.

The error occurred when executing a Cassandra query and where a UUID type was expected, some other data type was sent by the query. In my case, it was a String. Passing the right data type (UUID instead of String) resolved the issue.

Upvotes: 1

Numichi
Numichi

Reputation: 1092

It is work at me.

Use: findAllBy[object-property]In where [object-property] is name of property of the 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());

So if not contain uuid:

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

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

return this.myRepository.findAllByUuidIn(search);

Upvotes: 1

mp911de
mp911de

Reputation: 18127

It looks like as if IN queries using UUID are not possible by passing in a collection into a single bind value.

Here's what happens:

Spring Data transforms your String-query

SELECT * FROM entity WHERE id IN (:id)

into Cassandra's notation using positional query arguments

SELECT * FROM entity WHERE id IN (?)

and binds the given parameter to ?. Let's transform this into an executable piece of code:

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

When you run this snipped, then you'll end up with InvalidQueryException again. We can still make an IN query happen, but we need to unfold parameters:

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

In an ideal world, Cassandra could accept a List (or Set) of items to keep the query string agnostic against the actual number of arguments.

Upvotes: 1

Related Questions