没有提交Ignite CacheStoreAdapter
问题描述:
CacheStoreAdapter存在错误。当其方法sessionEnd被调用时,CacheStoreSessionResource的连接总是被关闭。没有任何例外。但事实上并没有提交交易,数据库也没有任何变化。我的代码非常简单。所有这些都是根据Ignite的原始示例完成的。没有提交Ignite CacheStoreAdapter
客户
IgniteCache<String, String> typeCache = ignite.getOrCreateCache("typeCache");
try (Transaction tx = ignite.transactions().txStart(TransactionConcurrency.PESSIMISTIC,
TransactionIsolation.REPEATABLE_READ)) {
typeCache.put("code", "name");
tx.commit();
}
catch (Exception e) {
log.error("ERROR. Put Type: " + type, e);
}
服务器:
public class CacheJdbcTypeStore extends CacheStoreAdapter<String, String> {
@CacheStoreSessionResource
private CacheStoreSession ses;
@Override
public void write(Cache.Entry<? extends String, ? extends String> entry) {
String key = entry.getKey();
String val = entry.getValue();
try (Connection conn = connection(ses)) {
try (PreparedStatement st = conn.prepareStatement(
"insert into t_type (code, name) values (?, ?)")) {
st.setString(1, key);
st.setString(2, val);
st.executeUpdate();
}
}
catch (Exception e) {
throw new CacheWriterException("Failed to write Type " + val, e);
}
}
@Override
public void sessionEnd(boolean commit) {
try (Connection conn = ses.attachment()) {
if (conn != null && !conn.isClosed() && ses.isWithinTransaction()) {
if (commit)
conn.commit();
else
conn.rollback();
}
}
catch (SQLException e) {
throw new CacheWriterException("Failed to end store session of Type cache", e);
}
}
private Connection connection(CacheStoreSession ses) throws Exception {
if (ses.isWithinTransaction()) {
Connection conn = ses.attachment();
/************************************/
/* Here conn always is closed. WHY???? */
/* As result transaction is never commited !!!! */
/************************************/
if (conn == null || conn.isClosed()) {
conn = openConnection(false);
ses.attach(conn);
}
return conn;
}
else {
return openConnection(true);
}
}
// Opens JDBC connection.
private Connection openConnection(boolean autocommit) throws Exception {
Connection conn = DriverManager.getConnection(url);
conn.setAutoCommit(autocommit);
return conn;
}
@Override
public String load(final String key) {
return null;
}
@Override
public void delete(Object key) {
}
}
配置
<property name="cacheConfiguration">
<list>
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="typeCache" />
<property name="cacheMode" value="PARTITIONED" />
<property name="atomicityMode" value="TRANSACTIONAL" />
<property name="backups" value="1" />
<property name="cacheStoreFactory">
<bean class="javax.cache.configuration.FactoryBuilder"
factory-method="factoryOf">
<constructor-arg
value="ru.raiffeisen.cache.store.jdbc.CacheJdbcTypeStore" />
</bean>
</property>
<property name="readThrough" value="true" />
<property name="writeThrough" value="true" />
</bean>
</list>
</property>
答
您使用try-与资源˚F或连接,所以每次离开此块时,都会关闭连接。
try (Connection conn = ses.attachment()) {}
我想你检查这实现:https://apacheignite.readme.io/docs/3rd-party-store#section-cachestore-example 但是,正如你所看到的,它提到,它不是一个事务。 请检查this缓存存储实施作为事务性缓存存储的示例
此外,要查看conn变量中的非空值,请尝试在事务内添加多个insert。
答
因此,Ignite文档包含jdbc-transactional CacheStoreAdapter实现的错误示例。 在上面的'服务器'代码中,我做了一些细微的更改,以消除错误。
try {
Connection conn = connection(ses);
try {
PreparedStatement st = conn.prepareStatement(
"insert into t_type (code, name) values (?, ?)");
st.setString(1, key);
st.setString(2, val);
st.executeUpdate();
}
}
catch (Exception e) {
throw new CacheWriterException("Failed to write Type " + val, e);
}
感谢您的想法。我会检查这个选项。 Just Ignite文档包含JDBC事务处理方式的此片段: //只要在IgniteCache上调用“put(...)”方法,就会调用此mehtod。 @覆盖公共无效写入(Cache.Entry 进入){ 试(连接康恩=连接()){ \t \t ......... } 赶上(的SQLException E){ 抛出新CacheWriterException(”无法写[key =“+ key +”,val =“+ val +']',e); } } –
更新的答案,据我所知,这是一个在doc中的问题,应该修复 –
是的,你是对的。这是Ignite文档中的问题。如果要在常规“try”语句内打开连接,则该代码会将数据放入数据库中。 –