找不到要求的操作的编解码器:[map< varchar,int> <-> java.util.Map];发行Apache Cassandra [英] Codec not found for requested operation: [map<varchar, int> <-> java.util.Map]; issue Apache Cassandra

查看:54
本文介绍了找不到要求的操作的编解码器:[map< varchar,int> <-> java.util.Map];发行Apache Cassandra的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含字段的表

CREATE TABLE app_category_agg (
    category text,
    app_count int,
    sp_count int,
    subscriber_count int,
    window_revenue bigint,
    top_apps frozen <list<map<text,int>>>,
    PRIMARY KEY (category)
);

当我尝试将其映射到kotlin模型

when I try to map it to kotlin model

@Table("app_category_agg")
class AppCategoryAggData {

    @PrimaryKeyColumn(name = "category", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
    lateinit var category: String

    @Column("app_count")
    var appCount: Int = 0

    @Column("sp_count")
    var spCount: Int = 0

    @Column("subscriber_count")
    var subscriberCount: Int = 0

    @Column("window_revenue")
    var windowRevenue: Long = 0

    @Column("top_apps")
    var topApps: List<Any> = arrayListOf()


}

interface AppCategoryAggRepository: CassandraRepository<AppCategoryAggData, String> {

    @Query(value = "SELECT * FROM analytics_info.app_category_agg")
    fun findAllAppCategoryAggData(): List<AppCategoryAggData>
}

我收到此错误

Query; CQL [SELECT * FROM analytics_info.app_category_agg]; Codec not found for requested operation: [map<varchar, int> <-> java.util.Map]; nested exception is com.datastax.driver.core.exceptions.CodecNotFoundException: Codec not found for requested operation: [map<varchar, int> <-> java.util.Map]

我该如何解决?我读过有关制作编解码器的信息,但对我来说还不是很清楚

how can I resolve it? I read about making codecs but it's not very much clear to me

推荐答案

我用您的结构创建了一个表,并填充了并带有示例数据:

I've created a table with your structure, and populated it with sample data:

insert into app_category_agg (category, app_count, sp_count, subscriber_count, window_revenue, top_apps) 
values('test', 2, 1, 10, 100, [{'t1':1, 't2':2}]);

对于Java驱动程序3中的对象映射器,其工作代码如下。

For object mapper from the Java driver 3, the working code is following.

类声明:

import com.datastax.driver.mapping.MappingManager
import com.datastax.driver.mapping.annotations.Column
import com.datastax.driver.mapping.annotations.PartitionKey
import com.datastax.driver.mapping.annotations.Table

@Table(keyspace = "test", name = "app_category_agg")
class AppCategoryAggData {

    @PartitionKey
    lateinit var category: String

    @Column(name = "app_count")
    var appCount: Int = 0

    @Column(name = "sp_count")
    var spCount: Int = 0

    @Column(name = "subscriber_count")
    var subscriberCount: Int = 0

    @Column(name = "window_revenue")
    var windowRevenue: Long = 0

    @Column(name = "top_apps")
    var topApps: List<Map<String, Int>> = emptyList()

    override fun toString(): String {
        return "AppCategoryAggData(category='$category', appCount=$appCount, spCount=$spCount, subscriberCount=$subscriberCount, windowRevenue=$windowRevenue, topApps=$topApps)"
    }
}

主要功能-它首先从Kotlin代码中插入数据,然后读取我预先插入的数据:

Main function - it first inserts data from Kotlin code, and then read the data that I pre-inserted:

import com.datastax.driver.core.Cluster

object KtTestObjMapper {
    @JvmStatic
    fun main(args: Array<String>) {
        val cluster = Cluster.builder()
                .addContactPoint("10.101.34.176")
                .build()
        val session = cluster.connect()

        val manager = MappingManager(session)
        val mapper = manager.mapper(AppCategoryAggData::class.java)

        val appObj = AppCategoryAggData()
        appObj.category = "kotlin"
        appObj.appCount = 5
        appObj.spCount = 10
        appObj.subscriberCount = 50
        appObj.windowRevenue = 10000
        appObj.topApps = listOf(mapOf("t2" to 2))
        mapper.save(appObj)

        val obj2 = mapper.get("test")
        print("obj2=$obj2")

        session.close()
        cluster.close()
    }
}

运行此代码时,收到以下输出:

When I run this code, I receive following output:

Object from =AppCategoryAggData(category='test', appCount=2, spCount=1, subscriberCount=10, windowRevenue=100, topApps=[{t1=1, t2=2}])

,当我使用 cqlsh 从表中选择数据时,我看到数据是由Kotlin插入的:

and when I select data from table using cqlsh, I see that data were inserted by Kotlin:

cqlsh:test> SELECT * from app_category_agg ;

 category | app_count | sp_count | subscriber_count | top_apps             | window_revenue
----------+-----------+----------+------------------+----------------------+----------------
     test |         2 |        1 |               10 | [{'t1': 1, 't2': 2}] |            100
   kotlin |         5 |       10 |               50 |          [{'t2': 2}] |          10000

(2 rows)

完整的代码在我的存储库中。该解决方案的一个缺点是它基于Java驱动程序3.x(该驱动程序的先前主要版本)。如果您对此没有严格要求,建议您使用同时适用于Cassandra& DSE,并且具有许多新功能。

The full code is in my repository. The one drawback of this solution is that it's based on the Java driver 3.x that is previous major release of the driver. If you don't have strict requirement for it, it's recommended to use latest major release - 4.x, that works with both Cassandra & DSE, and has a lot of new functionality.

尽管新版本中的对象映射器的工作方式有所不同-编译时注释使用了运行注释,而不是运行时注释,因此代码看起来有所不同,并且我们需要以不同的方式配置编译过程可能会更多相较于驱动程序3.x 复杂,但代码本身可能更简单(完整代码在这里)。

Although the object mapper in new version works differently - instead of run-time annotations, the compile annotations are used, so code looks differently, and we need to configure compilation process differently, and it could be more complicated compared to driver 3.x, but code itself could be simpler (full code is here).

我们需要定义数据类(实体):

We need to define data class (entity):

@Entity
@CqlName("app_category_agg")
data class AppCategoryAggData(
    @PartitionKey var category: String,
    @CqlName("app_count") var appCount: Int? = null,
    @CqlName("sp_count") var spCount: Int? = null,
    @CqlName("subscriber_count") var subscriberCount: Int? = null,
    @CqlName("window_revenue") var windowRevenue: Long? = null,
    @CqlName("top_apps") var topApps: List<Map<String, Int>>? = null
) {
    constructor() : this("")
}

定义DAO界面有2个操作(插入 findByCategory ):

@Dao
interface AppCategoryAggDao {
    @Insert
    fun insert(appCatAgg: AppCategoryAggData)

    @Select
    fun findByCategory(appCat: String): AppCategoryAggData?
}

定义映射程序以获得DAO:

@Mapper
interface AppCategoryMapper {
    @DaoFactory
    fun appCategoryDao(@DaoKeyspace keyspace: CqlIdentifier?): AppCategoryAggDao?
}

并使用它:

object KtTestObjMapper {
    @JvmStatic
    fun main(args: Array<String>) {
        val session = CqlSession.builder()
                .addContactPoint(InetSocketAddress("10.101.34.176", 9042))
                .build()

        // get mapper - please note that we need to use AppCategoryMapperBuilder
        // that is generated by annotation processor
        val mapper: AppCategoryMapper = AppCategoryMapperBuilder(session).build()

        val dao: AppCategoryAggDao? = mapper.appCategoryDao(CqlIdentifier.fromCql("test"))

        val appObj = AppCategoryAggData("kotlin2",
                10, 11, 12, 34,
                listOf(mapOf("t2" to 2)))
        dao?.insert(appObj)

        val obj2 = dao?.findByCategory("test")
        println("Object from =$obj2")

        session.close()
    }
}

与Java相比,变化是我们需要使用生成的类 AppCategoryMapperBuilder 来获取 AppCategoryMapper in:

The change compared to Java is that we need to use the generated class AppCategoryMapperBuilder to obtain the instance of AppCategoryMapper in:

val mapper: AppCategoryMapper = AppCategoryMapperBuilder(session).build()

这篇关于找不到要求的操作的编解码器:[map&lt; varchar,int&gt; &lt;-&gt; java.util.Map];发行Apache Cassandra的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆