2013-12-09 91 views
2

我期待存儲三個對象之間的關係列表,其中兩個相關對象將分別僅存在於列表中的一個關係中,第三個是計數我可以增加。這不是很普及,以SO在逃,但你可以看到我在這裏做什麼Java:如何保持三個對象之間的關係

public class Transaction implements AutoCloseable { 
    private final Connection conn; 
    private final Map<String, Map.Entry<PreparedStatement, Integer>> sts = new HashMap<>(); 

    Transaction(final Connection conn) throws SQLException { 
     conn.setAutoCommit(false); 
     this.conn = conn; 
    } 

    <T> void batch(final String st, final List<T> ts, 
      final BatchingInstructions<T> bi) throws SQLException { 
     final PreparedStatement stat; 
     int counter; 

     // if statement has already been created, retrieve statement and batch count 
     if (sts.containsKey(st)) { 
      final Map.Entry<PreparedStatement, Integer> m = sts.get(st); 
      stat = m.getKey(); 
      counter = m.getValue(); 
     } else { 
      // else create statement and batch count 
      stat = conn.prepareStatement(getInsert(st)); 
      counter = 0; 
      sts.put(st, // Can't do a new Map.Entry, really 
     } 

     for (final T t : ts) { 
      bi.batch(stat, t); 
      stat.addBatch(); 
      // increment how many times a batch has been added to the statement. 
      // execute batch if necessary. 
      if (++counter > 5000) { 
       stat.executeBatch(); 
      } 
     } 

    } 

    @Override 
    public void close() throws Exception { 
     for (final Map.Entry<PreparedStatement, Integer> m : sts.values()) { 
      if (m.getValue() > 0) { 
       m.getKey().executeBatch(); 
      } 
      m.getKey().close(); 
     } 
     conn.commit(); 
    } 

番石榴的表不完全正常工作,並且Map<String, Map<Statement, Integer>>也並不理想,而這一切都因需要複雜增加其中一個值(儘管我可能會使用這裏找到的mutableInt解決方案Most efficient way to increment a Map value in Java)。

我想知道是否有人知道這個問題的任何直截了當的解決方案,可能在第三方庫?


使用接受的答案,我能夠讓新班級做許多其他有用的事情。

class BatchPreparedStatement implements AutoCloseable { 
    private final PreparedStatement st; 
    private int counter = 0; 

    BatchPreparedStatement(final PreparedStatement st) { 
     this.st = st; 
    } 

    <T> void addBatch(final BatchingInstructions<T> bi, final T t) 
      throws SQLException { 
     bi.batch(st, t); 
     st.addBatch(); 
     executeBatch(10000); 
    } 

    void executeBatch(final int count) throws SQLException { 
     if (counter++ > count) { 
      st.executeBatch(); 
      counter = 0; 
     } 
    } 

    void finished() throws SQLException { 
     executeBatch(0); 
    } 

    @Override 
    public void close() throws Exception { 
     st.close(); 
    } 
} 

回答

1

爲什麼不建立一個包含語句,計數和處理所有addBatching加上其他雜項活動的類。

class BatchPreparedStatementHolder { 

    private int batchCount; 
    private PreparedStatement ps; 

    public BatchPreparedStatementHolder(PreparedStatement statement){ 
     batchCount = 0; 
     ps = statment; 
    } 

    public void addBatch(){ 
     ps.addBatch(); 
     // increment how many times a batch has been added to the statement. 
     // execute batch if necessary. 
     if (++batchCount> 5000) { 
      ps.executeBatch(); 
      batchCount = 0; 
     } 
    } 

    .... 

} 
0

該課程的建議是相當不錯的,但如果你只是需要一些簡單的重量,我會使用類似HashMap。 (其他語言稱這些「字典」)。我沒有時間閱讀您的所有代碼,但看起來您可能正在使用Google地圖?無論如何,你可以使關鍵字是自動遞增的值(如在數據庫中),並且該值可以是一個元組或其他兩個值的數組。查看包含HashMap以下鏈接很好的建議:

http://java67.blogspot.com/2013/02/10-examples-of-hashmap-in-java-programming-tutorial.html

或許只是做一個數組,其中的指數是指自動遞增的功能,內容是另一個數組?

不確定你需要什麼,但這些可能工作!

0

而不是保持和Map.Entry在地圖上你可以保持嵌套類..這將很容易處理..類似的東西..

class Transaction implements AutoCloseable { 
      private final Connection conn; 

      class MapValue { 
       PreparedStatement p; 
       int index ; 
       public MapValue(){} 
       public MapValue(PreparedStatement p , int i) 
       { 
        index= i; 
        this.p=p; 
       } 
      } 
      private final Map<String, MapValue> sts = new HashMap<>(); 

      Transaction(final Connection conn) throws SQLException { 
       conn.setAutoCommit(false); 
       this.conn = conn; 
      } 

      <T> void batch(final String st, final List<T> ts, 
        final BatchingInstructions<T> bi) throws SQLException { 
       final PreparedStatement stat; 
       int counter; 

       // if statement has already been created, retrieve statement and batch count 
       if (sts.containsKey(st)) { 
        MapValue m = sts.get(st); 
        stat = m.p; 
        counter = m.index; 
       } else { 
        // else create statement and batch count 

        stat = conn.prepareStatement(getInsert(st)); 
        MapValue m = new MapValue(stat, 0); 
        sts.put(st, m); 

       } 

       for (final T t : ts) { 
        bi.batch(stat, t); 
        stat.addBatch(); 
        // increment how many times a batch has been added to the statement. 
        // execute batch if necessary. 
        if (++counter > 5000) { 
         stat.executeBatch(); 
        } 
       } 
       @Override 
       public void close() throws Exception { 
        for (final Map.Entry<PreparedStatement, Integer> m : sts.values()) { 
         if (m.getValue() > 0) { 
          m.getKey().executeBatch(); 
         } 
         m.getKey().close(); 
        } 
        conn.commit(); 
       } 


     } 
相關問題