首页 文章

Spring boot apache点燃表未找到

提问于
浏览
0

首先,我对Spring Boot,REST API都很陌生,尤其是apache点燃,所以这可能是一个微不足道的问题,但我暂时无法解决它 .

我有一个包含几个表的Oracle 12c数据库,问题中的两个是:

create table la_license_count (
    total_count number not null default 100,
    active_count number not null default 0,
    temporary_count number not null default 0,
    id number not null
);

列'id'是pimary键,除此之外还有一个检查约束和一个唯一索引 .

create table la_license_mapping (
    client_id varchar2(200 byte) not null,
    license_count number not null default 0,
    license_type chat(1 byte) not null default 'F',
    registered_at date not null default sysdate,
    keepalive_time number,
    id number not null;
);

列'id'是pimary键,除此之外还有一个检查约束和一个唯一约束 .

需要基于Spring Boot的REST API来读取和更新此表 . Apache Ignite缓存层需要位于REST API和数据库之间 . 这实现如下 . 整个解决方案基于本指南:https://dzone.com/articles/in-memory-data-grid-with-apache-ignite,基于其他StackOverflow和各种论坛文章的一些更改,当它不工作时 .

数据库bean(自定义,因为密码是以自定义方式在日志中加密的) . DataSource本身工作正常,通过使用自动装配的JdbcTemplate执行CallableStatement进行测试;

@Configuration
public class DatabaseBean {

    @Autowired
    private ConfigReader configReader;

    @Bean(destroyMethod = "")
    public DataSource dataSource() {
        DatabaseSettings db = configReader.getDatabaseSettings();

        return DataSourceBuilder
                    .create()
                    .url(db.getConnectionString())
                    .username(db.getUserName())
                    .password(db.isPasswordEncrypted() ? Encryptor.decrypt(db.getPassword()) : db.getPassword())
                    .driverClassName(db.getDriverClassName())
                    .build();
    }

}

实体类:

public class LALicenseCount implements Serializable {

    private static final long serialVersionUID = -1L;
    private final AtomicLong ID_GEN = new AtomicLong();

    private Long id;
    private Long totalCount;
    private Long activeCount;
    private Long temporaryCount;

    // getters, setters

    public void init() {
        this.id = ID_GEN.getAndIncrement();
    }

    // Various methods for business logic

}

public class LALicenseMapping implements Serializable {

    private static final long serialVersionUID = -1L;
    private final AtomicLong ID_GEN = new AtomicLong();

    private Long id;

    @QuerySqlField(index = false)
    private String clientID;

    private Long licenseCount;

    @QuerySqlField(index = false)
    private String licenseType;

    private Date registeredAt;

    private Long keepaliveTime;

    // getters, setters

    public void init() {
        this.id = ID_GEN.getAndIncrement();
    }

    // Various methods for business logic

}

库:

@Repository
@RepositoryConfig(cacheName = "LALicenseCountCache")
public interface LALicenseCountRepository extends IgniteRepository<LALicenseCount, Long> {

}

@Repository
@RepositoryConfig(cacheName = "LALicenseMappingCache")
public interface LALicenseMappingRepository extends IgniteRepository<LALicenseMapping, Long> {

    List<LALicenseMapping> findByClientID(String clientID);

    List<LALicenseMapping> findByClientIDAndLicenseType(String clientID, String licenseType);

}

点燃 beans 子:

@Component
public class IgniteConfigurationBean {

    @Autowired
    private ConfigReader configReader;

    @Autowired
    private ApplicationContext applicationContext;

    @Bean
    public Ignite igniteInstance() {
        IgniteConfiguration cfg = new IgniteConfiguration();
        cfg.setIgniteInstanceName("ignite-1");
        cfg.setPeerClassLoadingEnabled(true);

        CacheConfiguration<Long, LALicenseCount> ccfg = new CacheConfiguration<>("LALicenseCountCache");
        ccfg.setIndexedTyped(Long.class, LALicenseCount.class);
        ccfg.setWriteBehind(true);
        ccfg.setReadThrough(true);
        ccfg.setWriteThrough(true);
        CacheJdbcPojoStoreFactory<Long, LALicenseCount> f = new CacheJdbcPojoStoreFactory<>();
        f.setDataSourceBean("dataSource");
        f.setDialect(new OracleDialect());
        JdbcType t = new JdbcType();
        t.setCacheName("LALicenseCountCache");
        t.setKeyType(Long.class);
        t.setValueType(LALicenseCount.class);
        t.setDatabaseTable("la_license_count");
        t.setDatabaseSchema(configReader.getDatabaseSettings().getUserName());
        t.setKeyFields(new JdbcTypeField(Types.INTEGER, "id", Long.class, "id"));
        t.setValueFields(
                    new JdbcTypeField(Types.INTEGER, "total_count", Long.class, "totalCount"),
                    new JdbcTypeField(Types.INTEGER, "active_count", Long.class, "activeCount"),
                    new JdbcTypeField(Types.INTEGER, "temporary_count", Long.class, "temporaryCount"));
        f.setTypes(t);
        ccfg.setCacheStoreFactory(f);

        CacheConfiguration<Long, LALicenseMapping> ccfg2 = new CacheConfiguration<>("LALicenseMappingCache");
        ccfg2.setIndexedTyped(Long.class, LALicenseMapping.class);
        ccfg2.setWriteBehind(true);
        ccfg2.setReadThrough(true);
        ccfg2.setWriteThrough(true);
        CacheJdbcPojoStoreFactory<Long, LALicenseMapping> f2 = new CacheJdbcPojoStoreFactory<>();
        f2.setDataSourceBean("dataSource");
        f2.setDialect(new OracleDialect());
        JdbcType t2 = new JdbcType();
        t2.setCacheName("LALicenseMappingCache");
        t2.setKeyType(Long.class);
        t2.setValueType(LALicenseCount.class);
        t2.setDatabaseTable("la_license_mapping");
        t2.setDatabaseSchema(configReader.getDatabaseSettings().getUserName());
        t2.setKeyFields(new JdbcTypeField(Types.INTEGER, "id", Long.class, "id"));
        t2.setValueFields(
                    new JdbcTypeField(Types.VARCHAR, "client_id", String.class, "clientID"),
                    new JdbcTypeField(Types.INTEGER, "license_count", Long.class, "licenseCount"),
                    new JdbcTypeField(Types.VARCHAR, "license_type", String.class, "licenseType"),
                    new JdbcTypeField(Types.DATE, "registered_at", java.sql.Date.class, "registeredAt"),
                    new JdbcTypeField(Types.INTEGER, "keepalive_time", Long.class, "keepaliveTime"));
        f2.setTypes(t2);
        ccfg2.setCacheStoreFactory(f2);

        cfg.setCacheConfiguration(ccfg, ccfg2);

        return IgniteSpring.start(cfg, applicationContext);
    }
}

主要应用类:

@SpringBootApplication
@EnableSwagger2
@ComponentScan(basePackages = {...})
@EnableIgniteRepositories("...")
public class Swagger2SpringBoot extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Swagger2SpringBoot.class);
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Swagger2SpringBoot.class, args);
    }
}

使用此配置,应用程序至少启动 . 我花了很长时间来计算如何设置bean,注释,依赖项等 . 现在我使用这些方式:

@Service
public class LicenseManager {

    @Autowired
    private LALicenseCountRepository laLicenseCountRepository;

    @Autowired
    private LALicenseMappingRepository laLicenseMappingRepository;

    @Autowired
    private Ignite ignite;

    private LALicenseCount licenseCount;
    private IgniteCache<Long, LALicenseCount> laLicenseCountCache;

    @PostConstruct
    public void init() {
        // There is only one LA_LICENSE_COUNT record always in the DB, and the ID is 1
        licenseCount = laLicenseCountRepository.findOne(1L);
        laLicenseCountCache = ignite.getOrCreateCache("LALicenseCountCache");
    }

    public Iterable<LALicenseMapping> getAllAllocatedLicenses() {
        return laLicenseMappingRepository.findAll();
    }

    public void allocateNewLicense(String clientID) {
        // prechecks

        laLicenseCountCache.query(
                    new SqlFieldsQuery(
                        sqlReader.getLicense().getUpdateAllocatedCounts()
                    ).setArgs(
                        licenseCount.getActiveCount(),
                        licenseCount.getTemporaryCount(),
                        1L
                    )
        );

        // remaining logic
    }

}

请在代码中备用关于1L常量的注释,这部分会改变,这段代码只是为了看看我是否可以读/写数据库 . 到目前为止,getAllAllocatedLicenses()函数似乎正在工作(没有异常发生),我在响应中成功接收到一个空的JSON数组 . 问题是我手动将记录输入数据库表后也收到一个空的JSON数组(不确定Ignite是否应该找到此记录,但我认为是) .

更大的问题是写操作失败 . 应该执行的SQL来自属性文件,如下所示:

update la_license_count set active_count = ?, temporary_count = ? where id = ?

我收到以下stacktraces(仅在laLicenseCountCache.query行之前显示):

2018-07-11 17:40:33.211 [http-nio-9080-exec-8] INFO  h.t.c.e.service.LicenseManager - 123456 - Processing new license allocation for client
2018-07-11 17:40:33.506 [http-nio-9080-exec-8] DEBUG h.t.c.e.service.LicenseManager - 123456 - Checks done, allocating new final license
2018-07-11 17:40:33.515 [http-nio-9080-exec-8] ERROR h.t.c.e.a.LAMiddlewareApiController - Unknown exception
javax.cache.CacheException: Failed to parse query. Table "LA_LICENSE_COUNT" not found; SQL statement:
update la_license_count set active_count = ?, temporary_count = ? where id = ? [42102-196]
        at org.apache.ignite.internal.processors.cache.IgniteCacheProxyImpl.query(IgniteCacheProxyImpl.java:676)
        at org.apache.ignite.internal.processors.cache.IgniteCacheProxyImpl.query(IgniteCacheProxyImpl.java:615)
        at org.apache.ignite.internal.processors.cache.GatewayProtectedCacheProxy.query(GatewayProtectedCacheProxy.java:356)
        at h.t.c.e.s.LicenseManager.allocateLicenseForCid(LicenseManager.java:127)
        at h.t.c.e.s.a.LAMiddlewareApiController.lAMiddlewareLicensesCidGet(LAMiddlewareApiController.java:147)
...
Caused by: org.apache.ignite.internal.processors.query.IgniteSQLException: Failed to parse query. Table "LA_LICENSE_COUNT" not found; SQL statement:
update la_license_count set active_count = ?, temporary_count = ? where id = ? [42102-196]
...
Caused by: org.h2.jdbc.JdbcSQLException: Table "LA_LICENSE_COUNT" not found; SQL statement:
update la_license_count set active_count = ?, temporary_count = ? where id = ? [42102-196]
        at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.command.Parser.readTableOrView(Parser.java:5552)
at org.h2.command.Parser.readTableOrView(Parser.java:5529)
at org.h2.command.Parser.readSimpleTableFilter(Parser.java:796)
at org.h2.command.Parser.parseUpdate(Parser.java:739)
at org.h2.command.Parser.parsePrepared(Parser.java:471)
at org.h2.command.Parser.parse(Parser.java:321)
at org.h2.command.Parser.parse(Parser.java:293)
at org.h2.command.Parser.prepareCommand(Parser.java:258)
at org.h2.engine.Session.prepareLocal(Session.java:578)
at org.h2.engine.Session.prepareCommand(Session.java:519)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1204)
at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:73)
at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:288)
at org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing.prepare0(IgniteH2Indexing.java:484)
at org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing.prepareStatement(IgniteH2Indexing.java:452)
at org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing.prepareStatement(IgniteH2Indexing.java:419)
at org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing.prepareStatementAndCaches(IgniteH2Indexing.java:2008)
... 85 common frames omitted

根据最后一个异常,它看起来像是在尝试访问Oracle数据库,就好像它是H2数据库一样?那可能吗?我为Ignite显式设置了OracleDialect,而Oracle JDBC驱动程序在pom.xml文件中 . 或者Ignite无法连接到DB? (我没有在日志中找到任何可以表明这一点的内容 . )

我在这里想念的是什么?

1 回答

  • 3

    如果你正在对Apache Ignite执行查询,它可能应该是 update "LALicenseCountCache".LALicenseCount set active_count = ?, temporary_count = ? where id = ?

    Ignite表名和模式!= Oracle表名和模式 . Ignite不实现SQL查询的透明代理 . 您不通过Ignite查询Oracle,而是查询Ignite自己的SQL .

    请注意,您应该执行 loadCache() ,以便最初将所有数据从Oracle提取到Apache Ignite 's cache. Otherwise your update won' t,因为缓存中的Ignite 's SQL only operates on what'已经存在 .

相关问题