2

我正在使用 spring-data-cassandra 模块。

我有一个使用 @Table 注释的带注释的 bean 和一个使用@PrimaryKeyClass

主键类有 5 个主键列(2 个分区和 3 个集群)。我的 2 列具有 name 属性,即:

@PrimaryKeyColumn(name="correlated_type", ordinal = 2, type= PrimaryKeyType.CLUSTERED)
private String correlatedType;

使用 CassandraTemplate 插入操作时,一切正常,但是当我使用cassandraTemplate.deleteAsynchronously(List<entities> list)列名时,不使用 name 属性解析列名,而是维护字段名。

我尝试对单个对象使用常规删除操作,并尝试使用 forceQuote = true 属性都没有帮助。

insert log sample:
[o.s.cassandra.core.CqlTemplate]     asynchronously executing [INSERT INTO identity_correlations(type,value,"**correlated_type**",ts,"**correlated_value**",extra) VALUES ('Participant','p5','Visitor',4,'R3',{'v':'1','labels':'b,c'}) USING TTL 34128000;

delete log sample:
[o.s.cassandra.core.CqlTemplate]     asynchronously executing [BEGIN BATCH DELETE  FROM identity_correlations WHERE **correlatedValue**='p5' AND **correlatedType**='Participant' AND type='Visit' AND value='v1' AND ts=1;DELETE  FROM identity_correlations WHERE correlatedValue='R3' AND correlatedType='Visitor' AND type='Participant' AND value='p5' AND ts=4;DELETE  FROM identity_correlations WHERE correlatedValue='R3' AND correlatedType='Visitor' AND type='Participant' AND value='p5' AND ts=3;APPLY BATCH;]

以前有人遇到过这个问题吗?

4

2 回答 2

1

在https://jira.spring.io/browse/DATACASS-142跟踪

讨论在https://groups.google.com/forum/#!forum/spring-data-cassandra(我们正在考虑放弃支持 stackoverflow.com)。

于 2014-07-29T15:45:53.393 回答
1

我和你有同样的问题,我认为我解决的方法对你有用。

我有一个使用@PrimaryKeyColumn 注释的Category.java 类。

@PrimaryKeyColumn(name = "language_id", ordinal = 1, type = PrimaryKeyType.PARTITIONED)
private String languageId;

我的选择、插入操作适用于 spring-data-cassandra,但我的删除操作不能。然后,spring-data-cassandra 参考提供的这一行不起作用:

cassandraOperations.delete(category);

http://docs.spring.io/spring-data/cassandra/docs/1.2.0.RC1/reference/html/

它引发异常“未知密钥标识符语言 ID”。

在内部生成的 CQL 语句如下:

DELETE FROM categories WHERE id='sdffsd' AND languageId='EN';

然后可以看到列名生成错误。

我的 Category.java 类如下:

package com.ehub.hmap.db.entities;

import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.data.cassandra.mapping.Column;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.mapping.Table;

@Table(value = "categories")
public class Category {

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

    @PrimaryKeyColumn(name = "language_id", ordinal = 1, type = PrimaryKeyType.PARTITIONED)
    private String languageId;

    @Column
    private String description;

    @Column
    private String tooltip;

    public Category(String id, String languageId, String description,
        String tooltip) {
        this.id = id;
        this.languageId = languageId;
        this.description = description;
        this.tooltip = tooltip;
    }

   public String getId() {
       return id;
   }

   public String getLanguageId() {
       return languageId;
   }

   public String getDescription() {
       return description;
   }

   public String getTooltip() {
       return tooltip;
   }

}

我从我的 Jersey REST 方法开始详细说明我的解决方案。

@POST
@Path("/deleteCategory")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces(MediaType.APPLICATION_JSON)
public Response deleteCategory(Category category) {

    dataManager.deleteEntity(Category.class, category);

    return Response.ok().build();
}

在我的 DataManager.java 类中,我有:

/**
 * Delete an entity at DB
 * 
 * @param entity: T type object
 * @return
 */
public <T> void deleteEntity(Class<T> typedClass, T entity) {

    // Start building the query
    Delete delete = QueryBuilder.delete().from(CassandraUtil.getTableName(typedClass));

    // Get a map<key,value> where key is the Db column name and value is the model name
    Map<String, String> map = CassandraUtil.getTableKeyMap(typedClass);

    for (Map.Entry<String, String> entry : map.entrySet())
    {
        // getKey() has the DB name, and getValue() has the model name
        delete.where(QueryBuilder.eq(entry.getKey(), CassandraUtil.getPropertyValue(entity, entry.getValue())));
    }
    cassandraOperations.execute(delete);
}

在我的 CassandraUtil.java 我有:

/**
 * Gets a <key,value> map where each key is the name of the column at Db and
 * value is the name of the field at your model.
 * 
 * @param Annotated Typed class corresponding to your entity model.
 * @return Map with Db column name and Model name.
 */
public static <T> Map<String,String> getTableKeyMap(Class<T> typedClass) {

    Map<String, String> map = new HashMap<String, String>();

    if (typedClass != null)
    {
        Field[] fields = typedClass.getDeclaredFields();

        for (Field field : fields) {

            try {
                String dbName = null;

                field.setAccessible(true);

                // Checks PrimaryKeyColumn annotation
                PrimaryKeyColumn pkc = field.getAnnotation(PrimaryKeyColumn.class);

                if (pkc != null)
                {
                    dbName = (pkc.name() != null) ? pkc.name(): field.getName();

                    // dbName gets the name of the column in Db
                    // getName() obtains the name in our model
                    map.put(dbName, field.getName());
                }
                // Checks PrimaryKey annotation
                PrimaryKey pk = field.getAnnotation(PrimaryKey.class);

                if (pk != null)
                {
                    dbName = (pk.value() != null) ? pk.value(): field.getName();

                    // dbName gets the name of the column in Db
                    // getName() obtains the name in our model
                    map.put(dbName, field.getName());
                }

            } catch (IllegalArgumentException
                    | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }
    return map;
}

public static <T> String getPropertyValue(T obj, String name) {
    String str = null;

    if (name != null)
    {
        try
        {
            Class<T> objClass = (Class<T>) obj.getClass();
            Field field = objClass.getDeclaredField(name);
            field.setAccessible(true);
            String val = field.get(obj) != null ? field.get(obj).toString(): "";

            return val;

        }

        catch (Exception iEx) {
        }

    }
    return str;
}

我希望它有帮助!我知道它可以更好地解决,所以......任何评论都应该受到赞赏。

于 2015-03-21T13:15:13.117 回答