有没有一种方法可以使用 QueryBuilder 将 Map<String,Object> 插入到 Cassandra Table 上以获得动态 table(Table with no model class)
Is there a way we can insert a Map<String,Object> onto the Cassandra Table using QueryBuilder for a dynamic table(Table with no model class)
public int save(String tableName, Map<String, Object> dataMap) throws IllegalAccessException {
SimpleStatement saveStatement = QueryBuilder.insertInto(tableName).values()
return 1;
}
我尝试了 QueryBuilder 的其他内置方法来整体保存地图值,但如果使用“values()”方法,则只能使用 map 类型的地图来保存数据,而且我已经有一个 map。这需要为动态 table p.s 完成。我对动态表不太熟悉。我尝试使用 return 类型整数的另一种方法是
public int save(String tableName, Map<String, Object> dataMap) throws IllegalAccessException {
SimpleStatement updateStatement = QueryBuilder.update(tableName)
.set(appendSet(dataMap))
.where(appendWhere(domainId))
.build();
log.info(updateStatement.getQuery());
return 1;
}
private Iterable<Assignment> appendSet(Map<String, Object> dataMap) throws IllegalAccessException {
List<Assignment> assignments = new ArrayList<>();
for (Field field : dataMap.getClass().getDeclaredFields()) {
if (!field.getName().equals("key")) {
try {
field.setAccessible(true);
if (field.get(dataMap) != null) {
if (field.getType().equals(Long.class)) {
assignments.add(Assignment.setColumn(field.getName(), literal(Long.valueOf(field.get(dataMap).toString()))));
} else {
assignments.add(Assignment.setColumn(field.getName(), literal(field.get(dataMap))));
}
}
} catch (IllegalAccessException e) {
log.catching(e);
}
}
}
return assignments;
}
private Iterable<Relation> appendWhere(Object key) {
List<Relation> relations = new ArrayList<>();
for (Field field : key.getClass().getDeclaredFields()) {
try {
field.setAccessible(true);
if (field.get(key) != null) {
if (field.getType().equals(Long.class)) {
relations.add(Relation.column(field.getName()).isEqualTo(literal(Long.valueOf(field.get(key).toString()))));
} else {
relations.add(Relation.column(field.getName()).isEqualTo(literal(field.get(key))));
}
}
} catch (IllegalAccessException e) {
log.catching(e);
}
}
return relations;
}
这可能也没有成功。我需要使用保存方法 return 一个整数,但我无法弄清楚如何使用 QueryBuilders 或 CassandraTemplate 将映射值插入到 cassandra table 本身。我正在使用 Cassandra 数据库,我的 table 是动态的。谁能给我推荐一篇好文章或其他什么?我找到了一些文章,但这些文章并没有帮助我将映射键值对插入 table,所以我很费力。任何帮助将不胜感激。
Cassandra 数据建模提醒
Cassandra 没有动态 table 之类的东西,它使用严格的模式。我会争辩说,如果你没有找到任何样本,那是因为它是一个反模式。
对于 Cassandra 数据库,您首先要设计查询,然后才定义 table,因为 **您只能过滤主键中的字段(where 子句的一部分)。我提到这个是因为 Iterable<Relation> appendWhere(Object key)
是可疑的,Cassandra 中没有连接也没有关系。
如果对同一数据出现新查询,则将数据复制到另一个 table(是的,对于关系型或面向文档的情况不同)
在您的应用程序初始化时,您 prepare
您的(静态)语句来验证语法并与服务器共享 PrepareStatementID
。
@PostConstruct
public void prepareStatements() {
PreparedStatement stmtCreateUser =
session.prepare(QueryBuilder.insertInto(USER_TABLENAME)
.value(USER_EMAIL, QueryBuilder.bindMarker())
.value(USER_FIRSTNAME, QueryBuilder.bindMarker())
.value(USER_LASTNAME, QueryBuilder.bindMarker())
.ifNotExists().build());
}
^ 注意到定义中使用的常量。稍后当您为额外的 table 重用列名或重命名列时,调试起来会更容易。
给定一个 table :
CREATE TABLE IF NOT EXISTS users_by_city (
city name,
firstname text,
lastname text,
email text,
PRIMARY KEY ((city), lastname, firstname, email)
);
合法但不推荐:
// This query is legal but never forget the where clause or you do full scan cluster
SELECT [fields] FROM users_by_city;
// This query is legal as you provide the partition in the where clause but having * in the select is hazardous if columns are added later.
SELECT * FROM users_by_city WHERE city=?
法律查询
SELECT firstname,lastname,email FROM users_by_city WHERE city=?
SELECT firstname,email FROM users_by_city WHERE city=? and lastname=?
// order is important
SELECT firstname,email FROM users_by_city WHERE city=? and lastname=? and firstname=?
非法查询
// city is required in PK
SELECT firstname,email FROM users_by_city WHERE lastname=? and firstname=?
// order of cluster columns are important
SELECT firstname,email FROM users_by_city WHERE a city=? and firstname=?
实施细节
所有这些提醒(抱歉,如果您已经知道所有这些想法,这些想法可能会在稍后出现...)这里有一些想法。
QueryBuilder
已经是动态构建查询的构建器,但查看您的代码您可以想到
插入
public SimpleStatement insertInto(String keyspace,
String tableName, Map<String, Object> fields) {
return QueryBuilder.insertInto(keyspace, tableName)
.values(fields.entrySet()
.stream().collect(Collectors.toMap(
entry -> entry.getKey(),
entry -> QueryBuilder.literal(entry.getValue()))))
.build();
}
SELECT
public SimpleStatement selectFrom(String keyspace, String tableName, Map<String, Relation> fields) {
return QueryBuilder.selectFrom(keyspace, tableName)
.columns(fields.keySet())
.where(fields.values())
.build();
}
额外资源
public int save(String tableName, Map<String, Object> dataMap) throws IllegalAccessException {
SimpleStatement saveStatement = QueryBuilder.insertInto(tableName).values()
return 1;
}
我尝试了 QueryBuilder 的其他内置方法来整体保存地图值,但如果使用“values()”方法,则只能使用 map
public int save(String tableName, Map<String, Object> dataMap) throws IllegalAccessException {
SimpleStatement updateStatement = QueryBuilder.update(tableName)
.set(appendSet(dataMap))
.where(appendWhere(domainId))
.build();
log.info(updateStatement.getQuery());
return 1;
}
private Iterable<Assignment> appendSet(Map<String, Object> dataMap) throws IllegalAccessException {
List<Assignment> assignments = new ArrayList<>();
for (Field field : dataMap.getClass().getDeclaredFields()) {
if (!field.getName().equals("key")) {
try {
field.setAccessible(true);
if (field.get(dataMap) != null) {
if (field.getType().equals(Long.class)) {
assignments.add(Assignment.setColumn(field.getName(), literal(Long.valueOf(field.get(dataMap).toString()))));
} else {
assignments.add(Assignment.setColumn(field.getName(), literal(field.get(dataMap))));
}
}
} catch (IllegalAccessException e) {
log.catching(e);
}
}
}
return assignments;
}
private Iterable<Relation> appendWhere(Object key) {
List<Relation> relations = new ArrayList<>();
for (Field field : key.getClass().getDeclaredFields()) {
try {
field.setAccessible(true);
if (field.get(key) != null) {
if (field.getType().equals(Long.class)) {
relations.add(Relation.column(field.getName()).isEqualTo(literal(Long.valueOf(field.get(key).toString()))));
} else {
relations.add(Relation.column(field.getName()).isEqualTo(literal(field.get(key))));
}
}
} catch (IllegalAccessException e) {
log.catching(e);
}
}
return relations;
}
这可能也没有成功。我需要使用保存方法 return 一个整数,但我无法弄清楚如何使用 QueryBuilders 或 CassandraTemplate 将映射值插入到 cassandra table 本身。我正在使用 Cassandra 数据库,我的 table 是动态的。谁能给我推荐一篇好文章或其他什么?我找到了一些文章,但这些文章并没有帮助我将映射键值对插入 table,所以我很费力。任何帮助将不胜感激。
Cassandra 数据建模提醒
Cassandra 没有动态 table 之类的东西,它使用严格的模式。我会争辩说,如果你没有找到任何样本,那是因为它是一个反模式。
对于 Cassandra 数据库,您首先要设计查询,然后才定义 table,因为 **您只能过滤主键中的字段(where 子句的一部分)。我提到这个是因为 Iterable<Relation> appendWhere(Object key)
是可疑的,Cassandra 中没有连接也没有关系。
如果对同一数据出现新查询,则将数据复制到另一个 table(是的,对于关系型或面向文档的情况不同)
在您的应用程序初始化时,您 prepare
您的(静态)语句来验证语法并与服务器共享 PrepareStatementID
。
@PostConstruct
public void prepareStatements() {
PreparedStatement stmtCreateUser =
session.prepare(QueryBuilder.insertInto(USER_TABLENAME)
.value(USER_EMAIL, QueryBuilder.bindMarker())
.value(USER_FIRSTNAME, QueryBuilder.bindMarker())
.value(USER_LASTNAME, QueryBuilder.bindMarker())
.ifNotExists().build());
}
^ 注意到定义中使用的常量。稍后当您为额外的 table 重用列名或重命名列时,调试起来会更容易。
给定一个 table :
CREATE TABLE IF NOT EXISTS users_by_city (
city name,
firstname text,
lastname text,
email text,
PRIMARY KEY ((city), lastname, firstname, email)
);
合法但不推荐:
// This query is legal but never forget the where clause or you do full scan cluster
SELECT [fields] FROM users_by_city;
// This query is legal as you provide the partition in the where clause but having * in the select is hazardous if columns are added later.
SELECT * FROM users_by_city WHERE city=?
法律查询
SELECT firstname,lastname,email FROM users_by_city WHERE city=?
SELECT firstname,email FROM users_by_city WHERE city=? and lastname=?
// order is important
SELECT firstname,email FROM users_by_city WHERE city=? and lastname=? and firstname=?
非法查询
// city is required in PK
SELECT firstname,email FROM users_by_city WHERE lastname=? and firstname=?
// order of cluster columns are important
SELECT firstname,email FROM users_by_city WHERE a city=? and firstname=?
实施细节
所有这些提醒(抱歉,如果您已经知道所有这些想法,这些想法可能会在稍后出现...)这里有一些想法。
QueryBuilder
已经是动态构建查询的构建器,但查看您的代码您可以想到
插入
public SimpleStatement insertInto(String keyspace,
String tableName, Map<String, Object> fields) {
return QueryBuilder.insertInto(keyspace, tableName)
.values(fields.entrySet()
.stream().collect(Collectors.toMap(
entry -> entry.getKey(),
entry -> QueryBuilder.literal(entry.getValue()))))
.build();
}
SELECT
public SimpleStatement selectFrom(String keyspace, String tableName, Map<String, Relation> fields) {
return QueryBuilder.selectFrom(keyspace, tableName)
.columns(fields.keySet())
.where(fields.values())
.build();
}
额外资源