Ignite Sping + Ignite SQL ClassCastException

时间:2018-12-17 11:15:01

标签: ignite

每次我尝试交替使用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使用它,则会发生类似“ ... ignite.IgniteRepositoryImpl#123456无法转换为SampleType.class”的ClassCastException。这使我相信这是与序列化有关的问题。如果我通过Ignite Spring创建表并尝试查询它,它还会给我“找不到用于xxxx的SQL表”。有人试图整合这两种观点吗?我在网上找到的示例仅假设使用Ignite Spring创建的缓存,并且Ignite的文档使这种互换似乎是可能且透明的。但是,显然不是这样,除非我忘记了什么。

最诚挚的问候,

卡洛斯·科斯塔

2 个答案:

答案 0 :(得分:4)

好的,我解决了我的问题。感谢大家的帮助。为了进一步阐明我的相当复杂的疑问,如果要尝试交替使用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”而不是“ My Cache Name”。我不知道为什么,但这似乎是一些默认行为,我没有在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)要插入数据,使用文档中显示的API方法,通过点燃,Spring就像一个超级按钮一样起作用。但是,通过DDL或JDBC插入时,您需要清楚地标识_KEY属性(显然是一个隐藏属性:P):

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

然后,我认为您可以互换使用这些API。

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

答案 1 :(得分:0)

您是否尝试导入Cache.Entry而不是Map.Entry?不幸的是,我看不到您的导入列表,但我怀疑您可以用前者替换后者,使代码正常工作。