如何解决从 Spring Boot 向 Cassandra 动态添加列
我正在尝试从 Spring Boot 应用程序动态添加新列。让我们说,每次发生事件 e 时,我想将一列添加到 Cassandra 表中,并具有明确定义的列名和类型。我试过这个代码:
@Query("alter table attributes.attributedata add ?0 ?1")
public void addColumn(String columnName,String dataType);
错误日志:
org.springframework.cassandra.support.exception.CassandraQuerySyntaxException: line 1:41 no viable alternative at input 'gac5' (alter table attributes.attributedata add ['gac]...); nested exception is com.datastax.driver.core.exceptions.SyntaxError: line 1:41 no viable alternative at input 'gac5' (alter table attributes.attributedata add ['gac]...)
at org.springframework.cassandra.support.CassandraExceptionTranslator.translateExceptionIfPossible(CassandraExceptionTranslator.java:132)
at org.springframework.cassandra.core.CqlTemplate.potentiallyConvertRuntimeException(CqlTemplate.java:946)
at org.springframework.cassandra.core.CqlTemplate.translateExceptionIfPossible(CqlTemplate.java:930)
at org.springframework.cassandra.core.CqlTemplate.translateExceptionIfPossible(CqlTemplate.java:912)
at org.springframework.cassandra.core.CqlTemplate.doExecute(CqlTemplate.java:278)
at org.springframework.cassandra.core.CqlTemplate.doExecute(CqlTemplate.java:559)
at org.springframework.cassandra.core.CqlTemplate.doExecute(CqlTemplate.java:549)
at org.springframework.cassandra.core.CqlTemplate.query(CqlTemplate.java:485)
at org.springframework.cassandra.core.CqlTemplate.query(CqlTemplate.java:510)
at org.springframework.cassandra.core.CqlTemplate.query(CqlTemplate.java:505)
at org.springframework.data.cassandra.core.CassandraTemplate.selectOne(CassandraTemplate.java:638)
at org.springframework.data.cassandra.core.CassandraTemplate.selectOne(CassandraTemplate.java:509)
at org.springframework.data.cassandra.repository.query.CassandraQueryExecution$SingleEntityExecution.execute(CassandraQueryExecution.java:104)
at org.springframework.data.cassandra.repository.query.CassandraQueryExecution$ResultProcessingExecution.execute(CassandraQueryExecution.java:143)
at org.springframework.data.cassandra.repository.query.AbstractCassandraQuery.execute(AbstractCassandraQuery.java:113)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:483)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:461)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:56)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
我也尝试将整个查询存储到一个字符串中,然后直接将字符串放入值中,这样
@Query(value="?0")
但这也不起作用。
此代码运行良好。如果从函数获得的值没有用单引号括起来,代码就可以工作。
@Query("alter table attributes.attributedata add dummy text")
public void addColumn(String columnName,String dataType);
有什么办法可以做到吗?请提出可能的替代方案。
解决方法
您可以使用 CONCAT 尝试类似的操作
@Query("alter table attributes.attributedata add CONCAT('%',:columnNameDataType,'%')")
public void addColumn(String columnNameDataType);
检查这个link
,可以如代码所示创建一个集群对象,然后是在其上执行查询的会话对象。要添加的列的名称和类型作为参数传递。
public void addColumn(String columnName,String columnType){
//Query
String query = "ALTER TABLE keyspace.tablename ADD " + columnName + " " + columnType;
//Creating Cluster object
Cluster cluster = Cluster.builder().addContactPoint("127.0.0.1").build();
//Creating Session object
Session session = cluster.connect();
//Executing the query
session.execute(query);
System.out.println("Column added");
}
为了优化代码,我们可以在应用程序启动期间只创建一次会话对象。这种场景的实现如下:
private Session session;
@EventListener(ApplicationReadyEvent.class)
private void createSessionObject(){
//Creating Cluster object
Cluster cluster = Cluster.builder().addContactPoint("127.0.0.1").build();
//Creating Session object
Session session = cluster.connect();
}
public void addColumn(String columnName,String columnType){
//Query
String query = "ALTER TABLE keyspace.tablename ADD " + columnName + " " + columnType;
if(session == null){
createSessionObject();
}
//Executing the query
session.execute(query);
System.out.println("Column added");
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。