2017-10-19 149 views
1

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> 

回答

1

您使用try-与资源˚F或连接,所以每次离开此块时,都会关闭连接。

try (Connection conn = ses.attachment()) {} 

我想你检查这实现:https://apacheignite.readme.io/docs/3rd-party-store#section-cachestore-example 但是,正如你所看到的,它提到,它不是一个事务。 请检查this缓存存储实施作为事务性缓存存储的示例

此外,要查看conn变量中的非空值,请尝试在事务内添加多个insert。

+0

感谢您的想法。我会检查这个选项。 Just Ignite文档包含JDBC事务处理方式的此片段: //只要在IgniteCache上调用“put(...)”方法,就会调用此mehtod。 @覆盖公共无效写入(Cache.Entry <龙,人>进入){ 试(连接康恩=连接()){ \t \t ......... } 赶上(的SQLException E){ 抛出新CacheWriterException(”无法写[key =“+ key +”,val =“+ val +']',e); } } –

+0

更新的答案,据我所知,这是一个在doc中的问题,应该修复 –

+0

是的,你是对的。这是Ignite文档中的问题。如果要在常规“try”语句内打开连接,则该代码会将数据放入数据库中。 –

1

因此,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); 
    }