Spring Data cassandra throws: Cannot obtain where clauses for entity

I never get this error message. What will you get error message if you have setter/getter methods or use Lombok project and add @Data annotation next to @Table? (If you use IntelliJ, you have to install Lombok plugin!)

In my answer, write comment if there is any result.

@Data
@Table
public class Transaction {

    @PrimaryKeyColumn(name = "id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
    private String id;

    @PrimaryKeyColumn(name = "timestamp", ordinal = 1, type = PrimaryKeyType.CLUSTERED)
    private Instant timestamp;

    private String currency;
}

UPDATE

TL;DR: Just add @Id above the attribute if you have one only @PrimaryKeyColumn. If you use more @PrimaryKeyColumn, you have to use:

  • @PrimaryKey and @PrimaryKeyClass (and you can use findById)
public interface TestRepository extends CassandraRepository<Test, KeyClass> {
}
@Data
@Table
public class Test {
    
    @PrimaryKey
    private KeyClass id;    

    @Data
    @PrimaryKeyClass
    public static class KeyClass { // You either give it a different name or move it in another file. Nevermind.
        @PrimaryKeyColumn(name = "id", type = PrimaryKeyType.PARTITIONED)
        private Integer id;
    
        @PrimaryKeyColumn(name = "data")
        private Integer data;
    }
}
  • or next interface:
public interface TestRepository extends CassandraRepository<Test, Integer> {
    Optional<Test> findByIdAndData(Integer id, Integer data);
}
@Data
@Table
public class Test {
    
    @PrimaryKeyColumn(name = "id", type = PrimaryKeyType.PARTITIONED)
    private Integer id;
    
    @PrimaryKeyColumn(name = "data")
    private Integer data;
}

With solo @PrimaryKeyColumn

Test data: enter image description here

-- auto-generated definition
CREATE TABLE test
(
    id   int PRIMARY KEY,
    data int
)
    WITH CACHING = {'keys': 'ALL', 'rows_per_partition': 'NONE'}
     AND COMPACTION = {'max_threshold': '32', 'min_threshold': '4', 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy'}
     AND COMPRESSION = {'class': 'org.apache.cassandra.io.compress.LZ4Compressor', 'chunk_length_in_kb': '64'}
     AND DCLOCAL_READ_REPAIR_CHANCE = 0.1;
public interface TestRepository extends CassandraRepository<Test, Integer> {
}
@Data
@Table
public class Test {
    
    /*
     * You can only use "findById" or "findallById" with @Id annotation.
     * @PrimaryKey contains the @Id itself, but ofc you have to configuration @PrimaryKeyClass.
     */
    @PrimaryKeyColumn(name = "id", type = PrimaryKeyType.PARTITIONED)
    @Id // <-- add
    private Integer id;
    
    @Column("data")
    private Integer data;
}

Test:

@SpringBootTest
class ApplicationTests {
    
    @Autowired
    private TestRepository testRepository;
    
    @Test
    void contextLoads() {
        var x = testRepository.findById(1).orElse(null);
        
        if(x == null) {
            fail();
        }
    
        assertEquals((int) x.getData(), 5);
    }
}

Result: enter image description here


With @PrimaryKey Table: enter image description here

public interface TestRepository extends CassandraRepository<Test, KeyClass> {
}
@Data
@Table
public class Test {
    
    @PrimaryKey
    private KeyClass id;    

    @Data
    @PrimaryKeyClass
    public static class KeyClass { // You either give it a different name or move it in another file. Nevermind.
        @PrimaryKeyColumn(name = "id", type = PrimaryKeyType.PARTITIONED)
        private Integer id;
    
        @PrimaryKeyColumn(name = "data")
        private Integer data;
    }
}

enter image description here


With JPA API

The second genetic type (what defined type of id) doesn’t matter what, on this solution.

enter image description here

enter image description here

enter image description here


If you want just query by PARTITION. CLUSTERED is exist!

Solution 1:

The second genetic type (what defined type of id) doesn’t matter what, on this solution.

enter image description here

Solution 2:

Rename id to something else and configure JPA that way.

The second genetic type (what defined type of id) doesn’t matter what, on this solution.

enter image description here

enter image description here

enter image description here

Solution with @PrimaryKeyClass

public interface TestRepository extends CassandraRepository<Test, KeyClass> {
    // findby[ID-1]_[ID-2](...)
    // ID-1 is mean: Test's "id" attribute
    // "_" is mean chain/access instance
    // ID-2 is mean: KeyClass's "id" attribute
    Optional<Test> findById_Id(Integer id);

    // Look this both:
    Optional<Test> findById_IdAndId_Data(Integer id, Integer data);
}

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top