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-Cassandra 1.3.2.RELEASE 是否支持@UDT ( http://docs.datastax.com/en/developer/java-driver/2.1/java-driver/reference/mappingUdts.html )?如果没有,我该如何为此添加解决方法
谢谢
在此处查看详细信息: https ://jira.spring.io/browse/DATACASS-172
我遇到了同样的问题,听起来好像没有(调试过程告诉我spring数据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 数据相关存储库如下所示:
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 注释的 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 {
..........
}
Spring Data Cassandra 现在支持用户定义的数据类型。最新版本 1.5.0.RELEASE 使用 Cassandra Data stax 驱动程序 3.1.3,因此它现在可以工作了。请按照以下步骤使其正常工作
如何在 Spring Data Cassandra 中使用 UserDefinedType(UDT) 功能:
我们需要使用最新的 jar 的 Spring data Cassandra (1.5.0.RELEASE)
组:'org.springframework.data',名称:'spring-data-cassandra',版本:'1.5.0.RELEASE'
确保它使用以下版本的 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
在 Cassandra 中创建用户定义类型:类型名称应与 POJO 类中定义的相同
地址数据类型
CREATE TYPE address_type (
id text,
address_type text,
first_name text,
phone text
);
在 Cassandra 中使用其中一列作为 UDT 创建列族:
员工表:
CREATE TABLE employee(employee_id uuid,employee_name 文本,冻结地址,主键 (employee_id,employee_name));
在域类中,定义带有注释的字段 -CassandraType 和 DataType 应该是 UDT:
@Table("employee") public class Employee { -- 其他字段-- @CassandraType(type = DataType.Name.UDT, userTypeName = "address_type") private Address address; }
为用户定义类型创建域类:我们需要确保用户定义类型模式中的列名必须与域类中的字段名相同。
@UserDefinedType("address_type") public class Address { @CassandraType(type = DataType.Name.TEXT) private String id; @CassandraType(type = DataType.Name.TEXT) 私有字符串地址类型;}
在 Cassandra 配置中,更改:
@Bean public CassandraMappingContext mappingContext() 抛出异常 { BasicCassandraMappingContext mappingContext = new BasicCassandraMappingContext(); mappingContext.setUserTypeResolver(new SimpleUserTypeResolver(cluster().getObject(), cassandraKeyspace)); 返回映射上下文;}
用户定义的类型应该在所有地方都具有相同的名称。例如