Java 关于spring数据中的异常org.springframework.core.convert.ConverterNotFoundException当我尝试插入一行时

Java 关于spring数据中的异常org.springframework.core.convert.ConverterNotFoundException当我尝试插入一行时,java,spring-data-cassandra,Java,Spring Data Cassandra,我是spring数据cassandra的新手,当我试图在cassandra表中创建一行时,我会遇到问题 这是我尝试运行测试时出现的异常,安装方法从未执行: org.springframework.core.convert.ConversionFailedException: **Failed to convert from type [java.util.HashSet<?>] to type [java.lang.String] for value '[unicon.matthew

我是spring数据cassandra的新手,当我试图在cassandra表中创建一行时,我会遇到问题

这是我尝试运行测试时出现的异常,安装方法从未执行:

org.springframework.core.convert.ConversionFailedException: **Failed to convert from type [java.util.HashSet<?>] to type [java.lang.String] for value '[unicon.matthews.entity.DataSync@79135a38[**
id=data_sync_id
orgId=identifier
tenantId=_tenand_id
syncDateTime=2017-09-25T13:35:14.153
syncType=all
syncStatus=fully_completed
]]'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [unicon.matthews.entity.DataSync] to type [java.lang.String]

...
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [unicon.matthews.entity.DataSync] to type [java.lang.String]
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:324)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:206)
at org.springframework.core.convert.support.CollectionToStringConverter.convert(CollectionToStringConverter.java:71)
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:37)
... 60 more

Cassandra是一个面向列的存储——Spring数据Cassandra将每个域类映射到一个表,没有关系,也不支持(还没有,但可能会出现)嵌入式对象。将数据结构展平到封闭对象映射到的表列的嵌入对象

但是,在表示数据结构的对象类上支持via
@UserDefinedType
。添加
@UserDefinedType
需要控制类/代码

如果您想继续使用该类,那么您仍然可以选择自己序列化数据,例如,使用Jackson并将JSON存储在单个Cassandra列中:

static class DataSyncWriteConverter implements Converter<DataSync, String> {

  public String convert(DataSync source) {

    try {
      return new ObjectMapper().writeValueAsString(source);
    } catch (IOException e) {
      throw new IllegalStateException(e);
    }
  }
}
静态类DataSyncWriteConverter实现转换器{
公共字符串转换(数据同步源){
试一试{
返回新的ObjectMapper().writeValueAsString(源);
}捕获(IOE异常){
抛出新的非法状态异常(e);
}
}
}
您还应该能够处理集合类型,这意味着您可以使用这种方法在Cassandra中的
Set
列中持久化
Set

最后一件事:使用第三方类有可能更改您无法控制的外部类。通过复制所有字段并将数据映射到第三方类来创建自己的数据结构,可以控制更改的生命周期

参考资料:


您希望如何在列存储中表示
DataSync
?您好@mp911de,谢谢您的回答。我想我需要属于DataSync的每个字段都作为属于该行的新列。我必须将这些字段从DataSync放入OrgCassandraTable pojo类吗?
import java.util.Optional;
import org.springframework.data.cassandra.repository.CassandraRepository;
import org.springframework.data.cassandra.repository.Query;

// this repo must implement something that paginates rows, because ALLOW FILTERING must not be used
public interface CassandraOrgRepository extends CassandraRepository<OrgCassandraTable> {

 @Query("SELECT * FROM org WHERE id = ?0")
 Optional<WrapperOrg> findById(final String id);
 @Query("SELECT * FROM org WHERE api_key = ?0 AND api_secret = ?1 ALLOW FILTERING")
 Optional<WrapperOrg> findByApiKeyAndApiSecret(final String apiKey, final String apiSecret);
 @Query("SELECT * FROM org WHERE api_key = ?0 ALLOW FILTERING")
 Optional<WrapperOrg> findByApiKey(final String apiKey);
 }
import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration;
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;

@Configuration
@EnableAutoConfiguration
public class CassandraConfiguration {

@Configuration
@EnableCassandraRepositories
static class CassandraConfig extends AbstractCassandraConfiguration {

private static final String KEYSPACE = "example";

@Override
public String getKeyspaceName() {
  return KEYSPACE;
}

@Override
public SchemaAction getSchemaAction() {
  return SchemaAction.RECREATE_DROP_UNUSED;
}

protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
  List<CreateKeyspaceSpecification> createKeyspaceSpecifications = new ArrayList<>();
  createKeyspaceSpecifications.add(getKeySpaceSpecification());
  return createKeyspaceSpecifications;
}

// Below method creates KEYSPACE if it doesnt exist.
private CreateKeyspaceSpecification getKeySpaceSpecification() {

  CreateKeyspaceSpecification pandaCoopKeyspace = new CreateKeyspaceSpecification();
  pandaCoopKeyspace.name(KEYSPACE);
  pandaCoopKeyspace.ifNotExists(true)
           .createKeyspace();
  return pandaCoopKeyspace;
}


@Override
public String getContactPoints() {
  return "localhost";
}

@Override
public String[] getEntityBasePackages() {
  return new String[] {"unicon.matthews.oneroster.service.repository"};
}
}
}
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Set;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.cassandra.mapping.CassandraType;
import org.springframework.data.cassandra.mapping.Column;
import org.springframework.data.cassandra.mapping.Indexed;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.mapping.Table;
import com.datastax.driver.core.DataType;
import unicon.matthews.entity.DataSync;
import unicon.matthews.oneroster.Org;
import unicon.matthews.oneroster.OrgType;
import unicon.matthews.oneroster.Status;

@Table(value=OrgCassandraTable.tableName)
public class OrgCassandraTable implements Serializable{

@org.springframework.data.annotation.Transient
public static final String tableName = "org";

@PrimaryKeyColumn(name = "id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
@CassandraType(type = DataType.Name.TEXT)
@Column("id")
private String id;

@Indexed
@CassandraType(type = DataType.Name.TEXT)
@Column("tenant_id")
private String tenantId;

@Indexed
@CassandraType(type = DataType.Name.TEXT)
@Column("api_key")
private String apiKey;

@Indexed
@CassandraType(type = DataType.Name.TEXT)
@Column("api_secret")
private String apiSecret;

@Indexed
@CassandraType(type = DataType.Name.TEXT)
@Column("org_source_id")
private String sourcedId;

@CassandraType(type = DataType.Name.TEXT)
@Column("org_status")
private String status;

@Column("org_metadata")
private Map<String, String> metadata;

@Column("org_dateLastModified")
@LastModifiedDate
private LocalDateTime dateLastModified;

@Column("org_name")
@CassandraType(type = DataType.Name.TEXT)
private String name;

// ojito que esto es un enum
@Column("org_type")
@CassandraType(type = DataType.Name.TEXT)
private String type;

@Column("org_identifier")
@CassandraType(type = DataType.Name.TEXT)
@Indexed
private String identifier;

// THIS FIELD LOOKS TO BE THE PROBLEM!
@Column("org_data_syncs")
@CassandraType(type = DataType.Name.TEXT)
private Set<DataSync> dataSyncs;

public OrgCassandraTable(){

}
public class DataSync implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
private String orgId;
private String tenantId;
private LocalDateTime syncDateTime;
private DataSync.DataSyncType syncType;
private DataSync.DataSyncStatus syncStatus;


...getters, setters, equals, hashCode, toString methods
}


...

// getters, setters, hashCode, equals, toString methods.
}
static class DataSyncWriteConverter implements Converter<DataSync, String> {

  public String convert(DataSync source) {

    try {
      return new ObjectMapper().writeValueAsString(source);
    } catch (IOException e) {
      throw new IllegalStateException(e);
    }
  }
}