Apache Ignite repository save method is doing only UPDATE instead of INSERT

338 Views Asked by At

I'm developing a Spring Boot + Impala app using Apache Ignite as cache store. The problem is IgniteRepository.save(key,entity) is only running UPDATE query instead of INSERT.

pom.xml

<ignite.version>2.14.0</ignite.version>

<dependency>
    <groupId>org.apache.ignite</groupId>
    <artifactId>ignite-spring-data-ext</artifactId>
    <version>2.0.0</version>
</dependency>

<dependency>
    <groupId>org.apache.ignite</groupId>
    <artifactId>ignite-core</artifactId>
    <version>${ignite.version}</version>
</dependency>

<dependency>
    <groupId>org.apache.ignite</groupId>
    <artifactId>ignite-indexing</artifactId>
    <version>${ignite.version}</version>
</dependency>

<dependency>
    <groupId>org.apache.ignite</groupId>
    <artifactId>ignite-spring</artifactId>
    <version>${ignite.version}</version>
</dependency>

Ignite Configuration :

IgniteConfiguration cfg = new IgniteConfiguration();
        cfg.setIgniteInstanceName("springDataNode");
        cfg.setPeerClassLoadingEnabled(true);

CacheConfiguration ccfg = new CacheConfiguration("XYZCache");
    ccfg.setIndexedTypes(Long.class, XYZ.class);
    ccfg.setCacheMode(CacheMode.PARTITIONED);
    ccfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);
    ccfg.setReadThrough(true);
    ccfg.setWriteThrough(true);
    ccfg.setWriteBehindEnabled(true);

    CacheJdbcPojoStoreFactory<Long, XYZ> factory = new CacheJdbcPojoStoreFactory<>();
    factory.setDataSourceBean("ImpalaDataSource");

    JdbcType jdbcType = new JdbcType();
    jdbcType.setCacheName("XYZCache");
    jdbcType.setKeyType(Long.class);
    jdbcType.setValueType(XYZ.class);
    jdbcType.setDatabaseTable("schema.table");

    jdbcType.setKeyFields(new JdbcTypeField(Types.BIGINT, "id", Long.class, "id"));
    jdbcType.setValueFields(
            new JdbcTypeField(Types.VARCHAR, "comments", String.class, "comments"),
            new JdbcTypeField(Types.BIGINT, "id", Long.class, "id")
            );
    factory.setTypes(jdbcType);
    ccfg.setCacheStoreFactory(factory);

    cfg.setCacheConfiguration(ccfg);
    return IgniteSpring.start(cfg, applicationContext);

Ignite Repository :

@RepositoryConfig(cacheName = "XYZCache")
public interface XYZRepository extends IgniteRepository<XYZ, Long> {

    @Query("select * FROM XYZ WHERE comments=?")
    List<XYZ> test(String comments);

    @Query("insert into XYZ (id,comments) values (?,?)")
    List<XYZ> customSave(Long id,String comments);

}

POJO :

@Data
public class XYZ implements Serializable {

    private static final long serialVersionUID = -2677636393779376050L;
    
    @QuerySqlField
    private Long id;
    @QuerySqlField
    private String comments;
}

Calling code:

xyzRepository.save(id, xyz);
xyzRepository.customSave(id, comments);

Both the methods are throwing error by running UPDATE query (instead of INSERT) which is not supported in Impala and also not what I intend to do :

Caused by: org.apache.ignite.internal.processors.cache.CachePartialUpdateCheckedException: Failed to update keys (retry update if possible).: [1671548234688] at org.apache.ignite.internal.processors.cache.GridCacheUtils.convertToCacheException(GridCacheUtils.java:1251) ~[ignite-core-2.14.0.jar:2.14.0]

Caused by: org.apache.ignite.IgniteCheckedException: Failed update entry in database [table=schema.table, entry=Entry [key=1671548234688, val=pkg.XYZ [idHash=1354181174, hash=991365654, id=1671548234688, comments=test]]] at org.apache.ignite.internal.processors.cache.store.GridCacheStoreManagerAdapter.put(GridCacheStoreManagerAdapter.java:593) at org.apache.ignite.internal.processors.cache.GridCacheMapEntry$AtomicCacheUpdateClosure.update(GridCacheMapEntry.java:6154) at org.apache.ignite.internal.processors.cache.GridCacheMapEntry$AtomicCacheUpdateClosure.call(GridCacheMapEntry.java:5918) at org.apache.ignite.internal.processors.cache.GridCacheMapEntry$AtomicCacheUpdateClosure.call(GridCacheMapEntry.java:5603) at org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree$Invoke.invokeClosure(BPlusTree.java:4254) at org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree$Invoke.access$5700(BPlusTree.java:4148) at org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree.invokeDown(BPlusTree.java:2226) at org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree.invoke(BPlusTree.java:2116) ... 146 common frames omitted Caused by: javax.cache.integration.CacheWriterException: Failed update entry in database [table=schema.table, entry=Entry [key=1671548234688, val=pkg.XYZ [idHash=1354181174, hash=991365654, id=1671548234688, comments=test]]] at org.apache.ignite.cache.store.jdbc.CacheAbstractJdbcStore.writeUpsert(CacheAbstractJdbcStore.java:978) at org.apache.ignite.cache.store.jdbc.CacheAbstractJdbcStore.write(CacheAbstractJdbcStore.java:1029) at org.apache.ignite.internal.processors.cache.store.GridCacheStoreManagerAdapter.put(GridCacheStoreManagerAdapter.java:585) ... 153 common frames omitted

Caused by: com.cloudera.impala.support.exceptions.GeneralException: [Cloudera]ImpalaJDBCDriver ERROR processing query/statement. Error Code: 0, SQL state: TStatus(statusCode:ERROR_STATUS, sqlState:HY000, errorMessage:AnalysisException: Impala does not support modifying a non-Kudu table: schema.table ), Query: UPDATE schema.table SET table.comments = 'test' WHERE (table.id = 1671548234688). ... 163 common frames omitted

What is the issue here? Why UPDATE is being forced by Apache Ignite? How can I change this behavior?

I also implemented Persistable interface and overrode isNew() to return true but it didn't work.

PS: Select queries are working fine (findAll, findById etc.) including the custom test() method. So, there is no datasource configuration issue and I am able to connect to Impala.

1

There are 1 best solutions below

1
On

This is likely because the dialect you are using does not have the merge set up.
See here: to understand the flow. This is per the stack trace you posted.

org.apache.ignite.cache.store.jdbc.CacheAbstractJdbcStore.writeUpsert(CacheAbstractJdbcStore.java:978) at  <br>
org.apache.ignite.cache.store.jdbc.CacheAbstractJdbcStore.write(CacheAbstractJdbcStore.java:1029) at <br>
org.apache.ignite.internal.processors.cache.store.GridCacheStoreManagerAdapter.put(GridCacheStoreManagerAdapter.java:585) ..

Alternatively, you can write your own data store factory.