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
SETtable
.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.
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.
Alternatively, you can write your own data store factory.