首页 > 解决方案 > 点燃 Spring + 点燃 SQL ClassCastException

问题描述

每次我尝试交替使用 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;
    }

样本类型存储库:

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 的文档表明这种交换是可能的并且是透明的。但是,显然不是,除非我忘记了什么。

此致,

卡洛斯·科斯塔

标签: javaspringignite

解决方案


好的,我解决了我的问题。感谢大家的帮助。为了进一步澄清我相当复杂的疑问,我将编写以下指南,如果尝试互换使用 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 文档中没有明确找到的一些默认行为。否则你可能会得到“找不到 SQL 表”:

...
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。

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


推荐阅读