2017-10-19 148 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); 
    }