【问题标题】:UserTypeResolver must not be nullUserTypeResolver 不能为空
【发布时间】:2017-09-04 18:06:47
【问题描述】:

我一直在尝试测试 Cassandra UDT 的插入,但一直遇到以下错误: 线程“main”java.lang.IllegalArgumentException 中的异常:UserTypeResolver 不能为空

在尝试了自己的方法之后,我尝试完全复制以下概述的方法: User Defined Type with spring-data-cassandra

但是,我仍然遇到同样的错误。

当我删除 UDT 并插入简单类型时,我能够插入到目标数据库,所以我知道我正在正确连接。我的配置如下:

@Configuration
@PropertySource(value = { "classpath:cassandra.properties" })
//@EnableCassandraRepositories(basePackages = { "org.spring.cassandra.example.repo" })
public class CassandraConfig {

private static final Logger LOG = LoggerFactory.getLogger(CassandraConfig.class);

@Autowired
private Environment env;

@Bean
public CassandraClusterFactoryBean cluster() {

    CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
    cluster.setContactPoints(env.getProperty("cassandra.contactpoints"));
    cluster.setPort(Integer.parseInt(env.getProperty("cassandra.port")));

    return cluster;
}

@Bean
public CassandraMappingContext mappingContext() {
    BasicCassandraMappingContext mappingContext = new BasicCassandraMappingContext();
    mappingContext.setUserTypeResolver(new SimpleUserTypeResolver(cluster().getObject(), "campaign_management"));
    return mappingContext;
}

@Bean
public CassandraConverter converter() {
    return new MappingCassandraConverter(mappingContext());
}

@Bean
public CassandraSessionFactoryBean session() throws Exception {

    CassandraSessionFactoryBean session = new CassandraSessionFactoryBean();
    session.setCluster(cluster().getObject());
    session.setKeyspaceName(env.getProperty("cassandra.keyspace"));
    session.setConverter(converter());
    session.setSchemaAction(SchemaAction.NONE);

    return session;
}

@Bean
public CassandraOperations cassandraTemplate() throws Exception {
    return new CassandraTemplate(session().getObject());
}
}

我的 Address 和 Employee 类与我上面引用的 SO 问题完全一样,我的 Main 很简单:

public class MainClass {

public static void main(String[] args) {

ApplicationContext service = new AnnotationConfigApplicationContext(CassandraConfig.class);

Employee employee = new Employee();
employee.setEmployee_id(UUID.randomUUID());
employee.setEmployee_name("Todd");
Address address = new Address();
address.setAddress_type("Home");
address.setId("ToddId");
employee.setAddress(address);
CassandraOperations operations = service.getBean("cassandraTemplate", CassandraOperations.class);

operations.insert(employee);

System.out.println("Done");
}
}

我正在使用:

datastax.cassandra.driver.version=3.1.3
spring.data.cassandra.version=1.5.1
spring.data.commons.version=1.13.1
spring.cql.version=1.5.1

上一个 SO 问题中引用的版本是 1.5.0,尽管 spring.io 将 1.5.1 列为当前版本,所以我正在使用它,但没有显示可用的 1.5.0。

任何帮助将不胜感激,因为这让我有些发疯。

【问题讨论】:

  • 你需要用SessionCassandraConverter构造CassandraTemplate
  • 谢谢,我是 Spring 新手,所以您的评论帮助我朝着正确的方向前进。想通了。
  • @TBlank 你能发布你的解决方案吗?

标签: user-defined-types spring-data-cassandra


【解决方案1】:

当您错过 cassandra 映射下的 UserTypeResolver 时,您通常会收到此错误,它本身由 cassandra 转换器使用,它本身由 Spring Data Cassandra 模板使用

详情:

假设您有一个基本的 Spring MVC 控制器并在其他地方运行......

Cassandra 中的 UserDefinedTypes 在 SET 和 MAP 中最有趣,下面的示例就是这种类型。

具有所有默认值的示例 Spring Bean 配置(Spring XML 应用程序上下文提取):

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:cassandra="http://www.springframework.org/schema/data/cassandra"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:task="http://www.springframework.org/schema/task"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
   http://www.springframework.org/schema/data/cassandra http://www.springframework.org/schema/data/cassandra/spring-cassandra.xsd
   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
...
<!-- ===== CASSANDRA ===== -->
<!-- Loads the properties into the Spring Context and uses them to fill in placeholders in bean definitions below -->
<context:property-placeholder location="/WEB-INF/spring/cassandra.properties" />

<!-- REQUIRED: The Cassandra Cluster -->
<cassandra:cluster contact-points="${cassandra.contactpoints}"
    port="${cassandra.port}" username="cassandra" password="cassandra"
    auth-info-provider-ref="authProvider" />

<!-- REQUIRED: The Cassandra Session, built from the Cluster, and attaching to a keyspace -->
<cassandra:session keyspace-name="${cassandra.keyspace}" />

<!-- REQUIRED: The Default Cassandra Mapping Context used by CassandraConverter 
     DO include a userTypeResolver for UDT support -->
<cassandra:mapping entity-base-packages="fr.woobe.model">
    <cassandra:user-type-resolver keyspace-name="${cassandra.keyspace}" />
</cassandra:mapping>

<!-- REQUIRED: The Default Cassandra Converter used by CassandraTemplate -->
<cassandra:converter />

<bean id="authProvider" class="com.datastax.driver.core.PlainTextAuthProvider">
    <constructor-arg index="0" value="myCassandraUser" />
    <constructor-arg index="1" value="somePassword" />
</bean>

<!-- REQUIRED: The Cassandra Template is the building block of all Spring Data Cassandra -->
<cassandra:template id="cassandraTemplate" />
...

然后在 java 中,通常在 Spring MVC 控制器中:

import org.springframework.data.cassandra.core.CassandraOperations;
...
// acquire DB template
CassandraOperations cOps = this.beanFactory.getBean("cassandraTemplate", CassandraOperations.class);
// for instance: load everything
List<MyData> rows = cOps.select("SELECT * FROM mydatatable", MyData.class);
// assuming an entry with index i exists...
Set<Pair> mySetOfPairs = rows.get(i).pairSet;
if (mySetOfPairs!=null)
   for (Pair p : mySetOfPairs) { 
        ... handle p.first and p.second ...
...

使用这种实体映射:

package example.model;
import java.util.Set;
import org.springframework.data.cassandra.core.mapping.CassandraType;
import org.springframework.data.cassandra.core.mapping.PrimaryKey;
import org.springframework.data.cassandra.core.mapping.Table;
import com.datastax.driver.core.DataType.Name;

@Table public class MyData {
   @PrimaryKey 
   public String myKey;
   // some other basic fields...
   public String moreStuff;
   // a SET of user defined 'pair type'
   @CassandraType(type = Name.SET, userTypeName = "pairType")
   public Set<Pair> pairSet;

   // your constructors and other methods here...
}

以及用户定义的实体,例如:

package example.model;
import org.springframework.data.cassandra.core.mapping.UserDefinedType;

@UserDefinedType("pairType")
public class Pair {
   public String first;
   public String second;

   public Pair() {
   }
   public Pair(String f, String s) {
    this.first= f;
    this.second= s;
   }
}

所有基于 Cassandra 表创建为:

CREATE TYPE pairType (first text, second text);

CREATE TABLE MyData (
  myKey text,
  moreStuff text,
  pairSet set<frozen<pairType>>,
  PRIMARY KEY (myKey)
  ) ;

INSERT INTO MyData (myKey, moreStuff, pairSet) 
  VALUES ('hello', 'world', { 
                  { first:'one', second:'two' }, 
                  { first:'out', second:'there' } } 
         ) ;

就 Maven 工件或库而言,如果您在 Web MVC Spring Controller 中运行,则确实需要 spring-webmvc,然后是 spring-context-support 和 spring-data-cassandra。 DataStax cassandra 驱动程序作为依赖项提供。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-23
    • 2017-06-16
    • 2020-10-06
    • 2015-10-27
    • 2021-01-22
    • 2016-08-18
    • 2013-04-30
    • 1970-01-01
    相关资源
    最近更新 更多