【问题标题】:Ignite Spring + Ignite SQL ClassCastException点燃 Spring + 点燃 SQL ClassCastException
【发布时间】:2019-09-04 01:02:04
【问题描述】:

每次我尝试交替使用 Ignite Spring API 和 Ignite SQL API 时,都会出现类转换异常或“找不到 xxxx 的 sql 表”

发生这种情况是因为我使用 ignite spring 创建了一个缓存并尝试使用 Ignite SQL API 使用数据,反之亦然:

@Configuration
@EnableIgniteRepositories("local.teste.is.api.repositories")
public class SpringAppCfg {

    @Bean
    public Ignite igniteInstance() {
        IgniteConfiguration cfg = new IgniteConfiguration();

        cfg.setIgniteInstanceName("springDataNode");
        cfg.setPeerClassLoadingEnabled(true);
        cfg.setClientMode(true);

        ...

        // Defining and creating a new cache to be used by Ignite Spring Data
        // repository.
        CacheConfiguration ccfg = new CacheConfiguration("SQL_PUBLIC_SAMPLETYPE3");

        // Setting SQL schema for the cache.
        ccfg.setIndexedTypes(Integer.class, SampleType.class);

        cfg.setCacheConfiguration(ccfg);

        Ignite ignite = Ignition.start(cfg);

        IgniteCache cache = ignite.getOrCreateCache(ccfg);

        SqlQuery sql = new SqlQuery(SampleType.class, "true");

        try (QueryCursor<Entry<Integer, SampleType>> cursor = cache.query(sql)) {
              for (Entry<Integer, SampleType> e : cursor)
                System.out.println(e.getValue().toString());
            }


        return ignite;
    }

SampleTypeRepository:

package local.teste.is.api.repositories;

import org.apache.ignite.springdata.repository.IgniteRepository;
import org.apache.ignite.springdata.repository.config.RepositoryConfig;

import local.al40.is.api.entities.SampleType;

@RepositoryConfig(cacheName = "SQL_PUBLIC_SAMPLETYPE")
public interface SampleTypeRepository extends IgniteRepository<SampleType, Integer>  {

    public SampleType getSampleTypeBySampleTypeId(Integer id);

}

使用 ignite Spring 的一切工作,包括保存和读取数据:

public class Application {

private static AnnotationConfigApplicationContext dataCtx;
private static SampleTypeRepository repo;

public static void main(String[] args) throws Exception {

    dataCtx = new AnnotationConfigApplicationContext();

    // Explicitly registering Spring configuration.
    dataCtx.register(SpringAppCfg.class);
    dataCtx.refresh();

    repo = dataCtx.getBean(SampleTypeRepository.class);

    System.out.println(repo);

    SampleType s = new SampleType(1, "teste");

    repo.save(s.getSampleTypeId(), s);

    System.out.println(repo.getSampleTypeBySampleTypeId(1).getSampleTypeName());

如果我通过 DDL 创建一个 Ignite SQL 表并尝试通过 Ignite Spring 使用它,就会发生这种情况,给我一个 ClassCastException,例如“...ignite.IgniteRepositoryImpl#123456 cannot be cast to SampleType.class”。这使我相信这是与序列化有关的问题。如果我通过 Ignite Spring 创建表并尝试查询它,它还会给我“找不到 xxxx 的 sql 表”。有人尝试过整合这两种观点吗?我在网上找到的示例仅假设使用 Ignite Spring 创建的缓存,并且 Ignite 的文档表明这种交换是可能的并且是透明的。但是,显然不是,除非我忘记了什么。

最好的问候,

卡洛斯·科斯塔

【问题讨论】:

  • 你能说明SampleTypeRepository类型是如何定义的吗?

标签: java spring ignite


【解决方案1】:

好的,我解决了我的问题。感谢大家的帮助。为了进一步澄清我相当复杂的疑问,我将编写以下指南,如果尝试交替使用 Ignite SQL 和 Ignite Spring,应考虑这些指南:

选项 1) 通过 Ignite Spring 创建缓存:

a) 在存储库类中明确定义缓存名称:

...
@RepositoryConfig(cacheName = "My Cache Name")
public interface SampleTypeRepository extends IgniteRepository<SampleType, Integer>  {

    public SampleType getSampleTypeBySampleTypeId(Integer id);

}

b) 在 Spring 应用中配置 Ignite 实例时定义缓存和索引:

...
CacheConfiguration ccfg = new CacheConfiguration("My Chache Name");

// Setting SQL schema for the cache.
ccfg.setIndexedTypes(Integer.class, SampleType.class);

config.setCacheConfiguration(ccfg);

Ignite ignite = Ignition.start(config);
...

c) 查询它,但请注意,由于某种原因,SQL 表名称是“SampleType”而不是“我的缓存名称”。我不知道,但这似乎是我在 Ignite Spring 文档中没有明确找到的一些默认行为。否则你可能会得到“no SQL table found for”:

...
IgniteCache cache = ignite.cache("My Chache Name");

        SqlFieldsQuery  sql = new SqlFieldsQuery("select * from SampleType");
        try (QueryCursor<List<?>> cursor = cache.query(sql)) {
              for (List<?> e : cursor)
                System.out.println(e.get(1));
            }

选项 2)通过 SQL DDL 创建缓存:

a) 通过明确定义 cache_name、key_type 和 value_type 来创建您的 SQL 表/缓存,使用与键和值类型对应的类的完全限定包名称:

CREATE TABLE IF NOT EXISTS SampleType(SampleTypeID int, SampleTypeName varchar, PRIMARY KEY (SampleTypeID)) WITH "cache_name=mycachename, key_type=java.lang.Integer, value_type=local.teste.is.api.entities.SampleType";

b) 要插入数据,通过 ignite Spring 就像使用文档中显示的 API 方法的魅力一样。但是,通过 DDL 或 JDBC 插入,您需要清楚地识别 _KEY 属性(显然是隐藏属性:P):

INSERT INTO SampleType(_KEY, SAMPLETYPEID, SAMPLETYPENAME) VALUES(?,?,?)

那么,我认为您可以互换使用这些 API。

最好的问候, 卡洛斯·科斯塔

【讨论】:

    【解决方案2】:

    您是否尝试过导入Cache.Entry 而不是Map.Entry?不幸的是,我看不到您的导入列表,但我怀疑您可以将后者替换为前者,让您的代码正常运行。

    【讨论】:

    • 你说得对,那是我的错,对不起。然而,这不是主要问题。问题实际上是序列化和必须创建 sql 表的方式。我将回答我自己关于定义 sql 表的方法的问题,该方法可以在 ignite kv api、ignite sql api 和 ignite spring 中使用,没有类转换异常、空指针或没有“找到的 sql 表”...谢谢您帮助。这确实解决了我问题的最初部分:)
    • @CarlosCosta 我建议您将后续问题拆分为单独的工单,以便根据指南分别回答。
    • 我设法理解并解决了这个问题。我对自己的问题给出了详细的回答,因为它可能会在将来对其他人有所帮助。我只是认为解决问题的一些步骤可能在文档中是明确的(例如,_KEY 属性,通过 Ignite Spring 创建的默认 SQL 表名,需要类的 fqdn,需要明确定义sql ddl 中的缓存名称)。或者也许我只是在几次尝试之间错过了一些东西,我不知道。
    猜你喜欢
    • 2012-01-22
    • 1970-01-01
    • 1970-01-01
    • 2020-09-27
    • 2015-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多