【问题标题】:Does Spring-data-Cassandra 1.3.2.RELEASE support UDT annotations?Spring-data-Cassandra 1.3.2.RELEASE 是否支持 UDT 注释?
【发布时间】:2016-04-17 15:59:43
【问题描述】:

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

谢谢

【问题讨论】:

  • 除非我记错了,否则我认为 spring-data 目前不支持映射 UDT,而是您必须直接使用 java 驱动程序映射 API。
  • 最新 Jar of Spring 数据 cassandra 支持 UDT。更多解释见下文。

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


【解决方案1】:

在此处查看详细信息: https://jira.spring.io/browse/DATACASS-172

我遇到了同样的问题,听起来好像没有( 调试过程向我展示了 Spring Data cassandra 检查 @Table、@Persistent 或 @PrimaryKeyClass 仅注解并引发异常 其他情况

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

但我找到了解决方案。 我想出了一种方法,可以让我管理包含 UDT 和不包含 UDT 的实体。在我的应用程序中,我使用 spring cassandra 数据项目以及直接 datastax 核心驱动程序。不包含 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 对象的实体的 Spring Data 相关存储库如下所示:

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 对象:

仅使用数据统计注释的 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 data 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 和不包含 UDT 的对象。

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

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

【讨论】:

  • 我看到您正在分隔带有和不带有 UDT 的对象,但在您的示例中,我无法弄清楚哪个是哪个!例如,您将 AccountDevice 用作带有 UDT 的对象。它的 POJO 在哪里?对于语句“SELECT * FROM account_devices”,你的POJO中定义的account_devices表在哪里?您是否错误地输入了错误的 POJO?看起来对于没有 UDT 的对象也是如此! account_users 表的 POJO 在哪里?
【解决方案2】:

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

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

  1. 我们需要使用最新的 jar 的 Spring data Cassandra (1.5.0.RELEASE)

    组:'org.springframework.data',名称:'spring-data-cassandra',版本:'1.5.0.RELEASE'

  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 类中定义的相同

地址数据类型

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

    员工表:

    创建表员工( employee_id uuid, 员工姓名文本, 地址冻结, 主键(employee_id、employee_name) );

  2. 在域类中,定义带有注解的字段-CassandraType,DataType应该是UDT:

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

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

    @UserDefinedType("address_type") 公共类地址 { @CassandraType(type = DataType.Name.TEXT) 私有字符串 id; @CassandraType(type = DataType.Name.TEXT) 私有字符串地址类型; }

  4. 在 Cassandra Config 中,更改此项:

    @Bean public CassandraMappingContext mappingContext() 抛出异常 { BasicCassandraMappingContext mappingContext = new BasicCassandraMappingContext(); mappingContext.setUserTypeResolver(new SimpleUserTypeResolver(cluster().getObject(), cassandraKeyspace)); 返回映射上下文; }

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

    • @UserDefinedType("address_type")
    • @CassandraType(type = DataType.Name.UDT, userTypeName = "address_type")
    • 创建类型地址类型

【讨论】:

    猜你喜欢
    • 2014-09-27
    • 1970-01-01
    • 2018-08-23
    • 1970-01-01
    • 2014-09-14
    • 2015-01-04
    • 2011-11-23
    • 1970-01-01
    • 2016-03-25
    相关资源
    最近更新 更多