Spring-data-Cassandra 1.3.2.RELEASE是否支持UDT注释?

时间:2016-01-12 21:06:08

标签: cassandra spring-data-cassandra cassandra-2.1

@UDT(http://docs.datastax.com/en/developer/java-driver/2.1/java-driver/reference/mappingUdts.html)是否受Spring-data-Cassandra 1.3.2.RELEASE的支持?如果没有,我该如何为此

添加变通方法

谢谢

2 个答案:

答案 0 :(得分:3)

详情请见: https://jira.spring.io/browse/DATACASS-172

我遇到了同样的问题,听起来却没有( 调试过程向我显示spring数据cassandra检查 @Table,@ Persistent或@PrimaryKeyClass仅注释并引发异常 在其他情况下

  

>   调用init方法失败;嵌套异常是org.springframework.data.cassandra.mapping.VerifierMappingExceptions:   Cassandra实体必须具有@ Table,@ Persistent或@PrimaryKeyClass Annotation

但我找到了解决方案。 我想出了允许我管理包含UDT的实体和不包含UDT的实体的方法。在我的应用程序中,我使用spring cassandra数据项目以及使用直接数据存储核心驱动程序。不包含UDT对象的存储库使用spring cassanta数据方法,包含UDT的对象使用自定义存储库。 自定义存储库使用datastax映射器,它们可以与UDT一起正常工作 (它们位于单独的包装中,请参阅下面的注释,为什么需要它):

package com.fyb.cassandra.custom.repositories.impl;

import java.util.List;
import java.util.UUID;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.cassandra.config.CassandraSessionFactoryBean;

import com.datastax.driver.core.ResultSet;
import com.datastax.driver.mapping.Mapper;
import com.datastax.driver.mapping.MappingManager;
import com.datastax.driver.mapping.Result;
import com.google.common.collect.Lists;
import com.fyb.cassandra.custom.repositories.AccountDeviceRepository;
import com.fyb.cassandra.dto.AccountDevice;

public class AccountDeviceRepositoryImpl implements AccountDeviceRepository {

    @Autowired
    public CassandraSessionFactoryBean session;

    private Mapper<AccountDevice> mapper;

    @PostConstruct
    void initialize() {
        mapper = new MappingManager(session.getObject()).mapper(AccountDevice.class);
    }

    @Override
    public List<AccountDevice> findAll() {
        return fetchByQuery("SELECT * FROM account_devices");
    }

    @Override
    public void save(AccountDevice accountDevice) {
        mapper.save(accountDevice);
    }

    @Override
    public void deleteByConditions(UUID accountId, UUID systemId, UUID deviceId) {
        final String query = "DELETE FROM account_devices where account_id =" + accountId + " AND system_id=" + systemId
                + " AND device_id=" + deviceId;
        session.getObject().execute(query);
    }

    @Override
    public List<AccountDevice> findByAccountId(UUID accountId) {
        final String query = "SELECT * FROM account_devices where account_id=" + accountId;
        return fetchByQuery(query);
    }

    /*
     * Take any valid CQL query and try to map result set to the given list of appropriates <T> types.
     */
    private List<AccountDevice> fetchByQuery(String query) {
        ResultSet results = session.getObject().execute(query);
        Result<AccountDevice> accountsDevices = mapper.map(results);
        List<AccountDevice> result = Lists.newArrayList();
        for (AccountDevice accountsDevice : accountsDevices) {
            result.add(accountsDevice);
        }
        return result;
    }
}

与管理不包含UDT对象的实体相关的弹簧数据相关回购看起来如下:

package com.fyb.cassandra.repositories;

import org.springframework.data.cassandra.repository.CassandraRepository;

import com.fyb.cassandra.dto.AccountUser;
import org.springframework.data.cassandra.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.UUID;

@Repository
public interface AccountUserRepository extends CassandraRepository<AccountUser> {

    @Query("SELECT * FROM account_users WHERE account_id=?0")
    List<AccountUser> findByAccountId(UUID accountId);
}

我已经测试了这个解决方案并且它100%正常工作。 另外我附上了我的POJO对象:

只使用数据stax annatation的Pojo:

package com.fyb.cassandra.dto;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import com.datastax.driver.mapping.annotations.ClusteringColumn;
import com.datastax.driver.mapping.annotations.Column;
import com.datastax.driver.mapping.annotations.Frozen;
import com.datastax.driver.mapping.annotations.FrozenValue;
import com.datastax.driver.mapping.annotations.PartitionKey;
import com.datastax.driver.mapping.annotations.Table;

@Table(name = "account_systems")
public class AccountSystem {

    @PartitionKey
    @Column(name = "account_id")
    private java.util.UUID accountId;

    @ClusteringColumn
    @Column(name = "system_id")
    private java.util.UUID systemId;

    @Frozen
    private Location location;

    @FrozenValue
    @Column(name = "user_token")
    private List<UserToken> userToken;

    @Column(name = "product_type_id")
    private int productTypeId;

    @Column(name = "serial_number")
    private String serialNumber;   
}

Pojo没有使用UDT并且只使用spring数据cassandra框架:

package com.fyb.cassandra.dto;

import java.util.Date;
import java.util.UUID;

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 = "accounts")
public class Account {

    @PrimaryKeyColumn(name = "account_id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
    private java.util.UUID accountId;

    @Column(value = "account_name")
    private String accountName;

    @Column(value = "currency")
    private String currency;    
}

请注意,以下实体使用不同的注释:

@PrimaryKeyColumn(name = "account_id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)and @PartitionKey
@ClusteringColumn and @PrimaryKeyColumn(name = "area_parent_id", ordinal = 2, type = PrimaryKeyType.CLUSTERED)

乍一看 - 它很不舒服,但它允许你使用包含UDT的对象,而不是。

一个重要的注意事项。那两个repos(使用UDT并且不应该驻留在不同的包中)导致Spring配置寻找带有repos的基础包:

@Configuration
@EnableCassandraRepositories(basePackages = {
        "com.fyb.cassandra.repositories" })
public class CassandraConfig {
..........
}

答案 1 :(得分:2)

Spring Data Cassandra现在支持用户定义的数据类型。最新版本1.5.0.RELEASE使用Cassandra Data stax驱动程序3.1.3,因此它现在正在运行。按照以下步骤使其正常工作

如何在Spring Data Cassandra中使用UserDefinedType(UDT)功能:

  1. 我们需要使用最新的Spring数据罐Cassandra(1.5.0.RELEASE)

    群组:&#39; org.springframework.data&#39;,名称:&#39; spring-data-cassandra&#39;,版本:&#39; 1.5.0.RELEASE&#39;

  2. 确保它使用jar的以下版本:

    datastax.cassandra.driver.version = 3.1.3 spring.data.cassandra.version = 1.5.0.RELEASE spring.data.commons.version = 1.13.0.RELEASE spring.cql.version = 1.5.0.RELEASE

  3. 在Cassandra中创建用户定义的类型:类型名称应与POJO类中定义的相同

  4. 地址数据类型

    CREATE TYPE address_type ( 
        id text, 
        address_type text, 
        first_name text, 
        phone text 
    );
    
    1. 在Cassandra中创建列系列,其中一列为UDT:

      员工表:

      CREATE TABLE员工(     employee_id uuid,     employee_name文本,     地址冻结,     主键(employee_id,employee_name) );

    2. 在域类中,使用注释-CassandraType定义字段,DataType应为UDT:

      @Table(&#34;员工&#34;)公共类员工{      - 其他领域 -     @CassandraType(type = DataType.Name.UDT,userTypeName =&#34; address_type&#34;)     私人地址; }

    3. 为用户定义的类型创建域类:我们需要确保用户定义的类型模式中的列名 必须与域类中的字段名称相同。

      @UserDefinedType(&#34; address_type&#34;)public class Address {@CassandraType(type = DataType.Name.TEXT) private String id; @CassandraType(type = DataType.Name.TEXT)private String address_type; }

    4. 在Cassandra配置中,更改此内容:

      @Bean public CassandraMappingContext mappingContext()抛出Exception {     BasicCassandraMappingContext mappingContext = new BasicCassandraMappingContext();     mappingContext.setUserTypeResolver(new SimpleUserTypeResolver(cluster()。getObject(),cassandraKeyspace));     return mappingContext; }

    5. 用户定义的类型应该在任何地方都具有相同的名称。例如

      • @UserDefinedType(&#34; address_type&#34)
      • @CassandraType(type = DataType.Name.UDT,userTypeName =&#34; address_type&#34;)
      • CREATE TYPE address_type