2015-04-24 16 views
8

Xin chào anh chàng tôi có thể tạo một hàng loạt với một PreparedStatement trong java như JDBC PreparedStatement hàng loạt tiếp tục chèn vào lỗi

for(Item item: list){ 
    ps.setString(1, item.getSome()); 
    ps.setString(2, item.getFoo()); 
    ps.setString(3, item.getBatman()); 
    statement.addBatch(); 

    if (++count % batchSize == 0) { 
     results = ps.executeBatch(); //execute parcial batch 

     if (results != null) 
      System.out.println(results.length); 
    } 

} 
results= ps.executeBatch(); //execute rest of batch 

Các máy chủ này

datebase là MySQL, trong bảng để chèn Tôi có một vài hạn chế

Bằng những hạn chế này khi tôi chèn tạo ra lỗi

tôi muốn chạy hàng loạt và bỏ qua lỗi, tại thời điểm này ném một ngoại lệ một kết thúc đợt

Trước khi tôi tạo ra hàng loạt Tôi có một Big cho tiết kiệm từng cái một như

//seudocode level 
For item 
Try{ 
    insert item 
}catch(E){nothing happens} 

Nhưng nó là rất chậm, trong một số trường hợp, procces batch 4000 mục, chèn 1500 và bỏ qua phần còn lại

Làm cách nào để thực hiện với lô?

EDIT

tôi sử dụng WebLogic để làm conections với trình điều khiển này mysql-connector-java-commercial-5.0.3-bin

tôi thử nghiệm các đặc tính này

1.

continueBatchOnError=true 

2.

rewriteBatchedStatements=true 

3.

continueBatchOnError=true 
rewriteBatchedStatements=true 

Và thêm connection.setAutoCommit(false); nhưng vẫn tiếp tục ném ngoại lệ trong các mục sao

EDIT

quên đề cập đến, tôi sử dụng cho kết nối Hibernate + mùa xuân

duy nhất Ví dụ For-Save được tạo trong Hibernate, nhưng đối với hiệu năng tôi đã thử sử dụng một JDBC Batch, trong các procces khác trong web Ứng dụng này cũng sử dụng JDBC với kết nối từ Hibernate và hoạt động tốt

này là đầy đủ mã

@Transactional 
public void saveMany(final List<Item> items) { 
    getMySqlSession().doWork(new Work() { 
     @Override 
     public void execute(Connection connection) throws SQLException { 

      StringBuilder sb = new StringBuilder(); 
      sb.append("INSERT INTO `FRT_DB`.`ITEM` "); 
      sb.append("("); 
      sb.append("`masterID`, "); 
      sb.append("`agent`, "); 
      sb.append("`rangeID`) "); 
      sb.append("VALUES "); 
      sb.append("("); 
      sb.append("?, "); 
      sb.append("?, "); 
      sb.append("?) "); 

      int[] results = null; 

      PreparedStatement ps = null; 

      try { 
       connection.setAutoCommit(false); 
       ps = connection.prepareStatement(sb.toString()); 


       final int batchSize = 250; 
       int count = 0; 

       for (Item item : items) { 

        if (item.getMasterId() != null) { 
         ps.setInt(1, item.getMasterId()); 
        } else 
         ps.setNull(1, java.sql.Types.INTEGER); 

        if (item.getAgent() != null) { 
         ps.setString(2, item.getAgent()); 
        } else 
         ps.setNull(2, Types.VARCHAR); 

        if (item.getRangeId() != null) 
         ps.setInt(3, item.getRangeId()); 
        else 
         ps.setNull(3, Types.INTEGER); 

        ps.addBatch(); 

        if (++count % batchSize == 0) { 
         results = ps.executeBatch(); 

         if (results != null) 
          System.out.println(results.length); 

        } 

       } 

       results= ps.executeBatch(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

     } 
    }); 
} 

này tạo ra ngoại lệ sau

java.sql.BatchUpdateException: Duplicate entry '1-000.002.725 'cho khóa ' masterID '

Nhưng tôi cần tiếp tục

cài đặt spring + hibernate can thiệp vào các thuộc tính của jdbc?Tôi không biết

+0

Bạn có sử dụng "MySQL Connector/J" trình điều khiển JDBC? Nếu vậy, hành vi mặc định phải là 'continueBatchOnError = true', mà dường như là những gì bạn muốn. –

+0

@GordThompson Tôi sử dụng weblogic cho kết nối, tôi thêm vào 'continueBatchOnError = true' và khởi động lại nhưng vấn đề vẫn còn tồn tại trong lần chèn đầu tiên' ps.executeBatch(); 'sau này đọc [SO post] (http: // stackoverflow .com/questions/26307760/mysql-and-jdbc-with-rewritebatchedstatements-true) và thêm 'rewriteBatchedStatements = true' này nhưng vẫn là Ngoại lệ – jasilva

Trả lời

6

Tôi nghĩ rằng nó có thể được tóm gọn trong một từ IGNORE

Khi bạn chạy batch với điều này

sb.append("INSERT IGNORE INTO `FRT_DB`.`ITEM` "); 

này KHÔNG ném một ngoại lệ realted với ép, điều này vượt qua , và dữ liệu cũ vẫn còn trong các hàng của bạn

Nếu bạn cần lưu 'dữ liệu mới', bạn thay đổi cho Tuyên bố INSERT ... ON DUPLICATE KEY, nhưng, hiện tại bạn không cần nó.

Cam kết hoặc khôi phục không cần thiết trong mã của bạn @Transactional phù hợp với bạn.

lớn try { chỉ sụp đổ của bạn trong SqlException không BatchUpdateException

Bạn chỉ cần thêm allowMultiQueries beacuse khác và mặc định true

http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html

+0

Hoàn hảo cho tôi! – jasilva

Các vấn đề liên quan