2013-12-09 3 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. (другие языки называют эти словари). У меня нет времени, чтобы прочитать весь ваш код, но похоже, что вы можете использовать Карты?

В любом случае, вы можете сделать ключ автоматически увеличиваемым значением (как в базах данных), а значение может быть, например, кортежем или массивом двух других значений. Смотрите ссылку на хороший совет по HashMaps:

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(); 
       } 


     } 
Смежные вопросы