如何解决Spring Data Cassandra抛出:无法获取实体的where子句
iam尝试使用Spring数据cassandra通过REST API与cassandra / scyllaDB通信。 我有实体
@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;
}
带有存储库
@Repository
public interface TransactionRepository extends CassandraRepository<Transaction,String> {
}
和在REST控制器中调用的服务
@Service
public class TransactionServiceImpl implements TransactionService{
@Autowired
private TransactionRepository transactionRepository;
private Transaction getTransaction(String transactionId) {
return transactionRepository.findById(transactionId)
.orElseThrow(() -> new NotFoundException("Transaction with provided " + transactionId + " does not exist."));
}
}
当我调用所需的REST端点(在该端点上提供正确的transactionId)时,会引发异常。
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: Cannot obtain where clauses for
entity [com.example.dao.entity.Transaction] using [id123456]
我进行了一些调查,但是实体类中提供的组合键应该有效。我在做什么错?
表的型号:
CREATE TABLE etl.transaction
(
id text,timestamp timestamp,currency ascii,PRIMARY KEY (id,timestamp)
)
WITH CLUSTERING ORDER BY (timestamp ASC) AND
default_time_to_live = 157680000; // 5 years in seconds
解决方法
我从未收到此错误消息。如果您有setter / getter方法或使用Lombok项目并在@Table旁边添加@Data注释,将会收到什么错误消息? (如果使用IntelliJ,则必须安装Lombok插件!)
在我的答案中,如果有任何结果,请写评论。
@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;
}
更新
TL; DR:如果您只有一个@PrimaryKeyColumn,则只需在属性上方添加@Id。如果您使用更多@PrimaryKeyColumn,则必须使用:
- @PrimaryKey和@PrimaryKeyClass(您可以使用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;
}
}
- 或下一个界面:
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;
}
与@PrimaryKeyColumn
一起
-- 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;
}
测试:
@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);
}
}
public interface TestRepository extends CassandraRepository<Test,type = PrimaryKeyType.PARTITIONED)
private Integer id;
@PrimaryKeyColumn(name = "data")
private Integer data;
}
}
使用JPA API
在此解决方案上,第二种遗传类型(定义的id类型)无关紧要。
如果只想按PARTITION进行查询。集群存在!
解决方案1:
在此解决方案上,第二种遗传类型(定义的id类型)无关紧要。
解决方案2:
将id
重命名为其他名称,然后以这种方式配置JPA。
在此解决方案上,第二种遗传类型(定义的id类型)无关紧要。
使用@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);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。