I am using Spring-Reactive and Reactive-Cassandra [spring-boot-starter-data-cassandra-reactive] to access tables on Cassandra. I am able to access simple tables with a single column representing the Primary Key such as:
user_name: partition_key
address: regular
But when it comes to a more complicated table such as the following, I am unable to fetch any info from Cassandra:
user_name: partition_key
department_name: clustering
address: regular
Following is how I have written my @Configuration and @Repository in Spring reactive:
Config:
@AllArgsConstructor
@Table(value = "user_table")
public class UserConfig {
@Getter
@PrimaryKey
private UserKey key;
@Column("address")
@Getter
private String address;
}
Primary Key Class:
@Getter
@PrimaryKeyClass
@AllArgsConstructor
public class UserKey {
@PrimaryKeyColumn(name = "user_name", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
private String userName;
@PrimaryKeyColumn(name = "department_name", ordinal = 1, type = PrimaryKeyType.CLUSTERED)
private String departmentName;
}
Repository:
@Repository
public interface UserRepository extends ReactiveCassandraRepository<UserConfig, UserKey> {
Mono<UserConfig> findByKeyUserNameAndKeyDepartmentName(String userName, String departmentName);
}
My Cassandra config class is as follows:
@Configuration
@EnableReactiveCassandraRepositories
public class CassandraConfig extends AbstractReactiveCassandraConfiguration {
@Value("${spring.cassandra.contact-points}")
private String contactPoints;
@Value("${spring.cassandra.local-datacenter}")
private String localDatacenter;
@Value("${spring.cassandra.port}")
private int port;
@Value("${spring.cassandra.keyspace-name}")
private String keySpace;
@Value("${spring.cassandra.username}")
private String username;
@Value("${spring.cassandra.password}")
private String password;
@Value("${spring.cassandra.schema-action}")
private SchemaAction schemaAction;
@Override
protected String getContactPoints() {
return contactPoints;
}
@Override
protected int getPort() {
return port;
}
@Override
public SchemaAction getSchemaAction() {
return schemaAction;
}
@Override
protected String getKeyspaceName() {
return keySpace;
}
@Bean
@Override
public CqlSessionFactoryBean cassandraSession() {
CqlSessionFactoryBean cqlSessionFactoryBean = new CqlSessionFactoryBean();
cqlSessionFactoryBean.setUsername(username);
cqlSessionFactoryBean.setPassword(password);
cqlSessionFactoryBean.setKeyspaceName(keySpace);
cqlSessionFactoryBean.setLocalDatacenter(localDatacenter);
cqlSessionFactoryBean.setPort(port);
cqlSessionFactoryBean.setContactPoints(contactPoints);
return cqlSessionFactoryBean;
}
}
All the documentation I have followed does the exact same thing that I am doing above. What am I missing here? Kindly help.
This worked for me:
Table Class:
@Data
@AllArgsConstructor
@Table(value = "user_table")
public class UserConfig implements Serializable {
@PrimaryKeyColumn(name = "user_name", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
private String userName;
@PrimaryKeyColumn(name = "department_name", ordinal = 1, type = PrimaryKeyType.CLUSTERED, ordering = Ordering.ASCENDING)
private String departmentName;
@Column(value = "address")
private String address;
}
Repository:
@Repository
public interface UserRepository extends ReactiveCassandraRepository<UserConfig, String> {
@Query("SELECT * from user_table where user_name=?0")
Flux<UserConfig> findByUserName(String userName);
@Query("SELECT * from user_table where user_name=?0 and department_name=?1")
Flux<UserConfig> findByUserNameAndDepartmentName(String userName, String departmentName);
}
The change mainly here is with respect to how the Repository interface methods are defined with @Query.