5

Java アプリケーションからデータベース (SQL Server 2012 など) への一括挿入を実行するさまざまな方法を探しています。エンティティの数だけデータベースを呼び出すことなく、多くのエンティティを非常に効率的にデータベースに挿入する必要があります。

私の要件は、エンティティの一括挿入を実行することです。データベースへのエンティティの挿入には、1 つ以上のテーブルへのデータの挿入が含まれる可能性があります。私が考えることができる2つの方法は次のとおりです。

  1. SQL ステートメントのバッチを動的に生成し、ネイティブ JDBC サポートを利用してデータベースに対して実行します。

  2. すべてのエンティティの XML 表現を構築し、生成された XML を渡してストアド プロシージャを呼び出します。ストアド プロシージャは、XML の解析とエンティティのデータベースへの挿入を処理します。

私はJavaが初めてで、利用可能なフレームワークについて十分な知識がありません。IMO、上記の 2 つのアプローチは非常に素朴で、利用可能なフレームワークを活用していないようです。一括挿入を実現するさまざまな方法とその長所と短所を共有するよう専門家に依頼しています。私は効率的な方法で問題を解決する MyBatis、Spring-MyBatis、Spring-JDBC、JDBC などを受け入れています。

ありがとう。

4

3 に答える 3

10

デモがあります、JDBC バッチ処理ファイル:demo.txt 内容

1899942 、デモ
1 1899944 、デモ 2
1899946 、デモ 3
1899948 、デモ 4

データを挿入する ファイルの内容を読み取る

私のコード:

public class Test2 {
        public static void main(String[] args) {
            long start = System.currentTimeMillis();
            String sql = "insert into mobile_place(number,place) values(?,?)";
            int count=0;
            PreparedStatement pstmt = null;
            Connection conn = JDBCUtil.getConnection();
            try {
                pstmt = conn.prepareStatement(sql);

                InputStreamReader is = new InputStreamReader(new FileInputStream(new File("D:/CC.txt")),"utf-8");
                BufferedReader br = new BufferedReader(is);
                conn.setAutoCommit(false);

                String s1 = null;
                String s2 = null;
                while(br.readLine() != null){
                    count++;
                    String str = br.readLine().toString().trim();
                    s1 = str.substring(0, str.indexOf(","));
                    s2 = str.substring(str.indexOf(",")+1,str.length());

                    pstmt.setString(1, s1);
                    pstmt.setString(2, s2);
                    pstmt.addBatch();

                    if(count%1000==0){
                        pstmt.executeBatch();
                        conn.commit();
                        conn.close();
                        conn = JDBCUtil.getConnection();
                        conn.setAutoCommit(false);
                        pstmt = conn.prepareStatement(sql);
                    }
                    System.out.println("insert "+count+"line");
                }
                if(count%1000!=0){
                    pstmt.executeBatch();
                    conn.commit();
                }
                long end = System.currentTimeMillis();

                System.out.println("Total time spent:"+(end-start));
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                try {
                    pstmt.close();
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    //getConnection()//get jdbc Connection
    public static Connection getConnection(){ 
    try { 
    Class.forName("com.mysql.jdbc.Driver"); 
    } catch (ClassNotFoundException e) { 
    e.printStackTrace(); 
    } 
    try { 
    conn = DriverManager.getConnection(url, userName, password); 
    } catch (SQLException e) { 
    e.printStackTrace(); 
    } 
    return conn; 
    }

初めて話します、私が助けてくれることを願っています

私は上記のデモです PreparedStatement を使用します [Read data calls a PreparedStatement one-off insert]

JDBC バッチには 3 つの方法があります。1.PreparedStatement デモを使用します。

try {   
      Class.forName("com.mysql.jdbc.Driver");   
      conn = DriverManager.getConnection(o_url, userName, password);   
      conn.setAutoCommit(false);   
      String sql = "INSERT adlogs(ip,website,yyyymmdd,hour,object_id) VALUES(?,?,?,?,?)";   
      PreparedStatement prest = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);   
      for(int x = 0; x < size; x++){   
         prest.setString(1, "192.168.1.1");   
         prest.setString(2, "localhost");   
         prest.setString(3, "20081009");   
         prest.setInt(4, 8);   
         prest.setString(5, "11111111");   
         prest.addBatch();   
      }   
      prest.executeBatch();   
      conn.commit();   
      conn.close();   
} catch (SQLException ex) {   
   Logger.getLogger(MyLogger.class.getName()).log(Level.SEVERE, null, ex);   
}   

2.Statement.addBatch メソッドのデモを使用します。

conn.setAutoCommit(false);   
 Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);   
 for(int x = 0; x < size; x++){   
   stmt.addBatch("INSERT INTO adlogs(ip,website,yyyymmdd,hour,object_id) VALUES('192.168.1.3', 'localhost','20081009',8,'23123')");   
 }   
stmt.executeBatch();   
conn.commit(); 

3. Statement デモの直接使用:

conn.setAutoCommit(false);   
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,   
                                    ResultSet.CONCUR_READ_ONLY);   
for(int x = 0; x < size; x++){   
   stmt.execute("INSERT INTO adlogs(ip,website,yyyymmdd,hour,object_id) VALUES('192.168.1.3', 'localhost','20081009',8,'23123')");   
}   
conn.commit(); 

上記の方法で 100000 個のデータを挿入 時間がかかる: メソッド 1:17.844s メソッド 2:18.421s メソッド 3:16.359s

于 2013-03-09T13:29:20.063 に答える
2

4.1 以降のバージョンの MS JDBC には SQLServerBulkCopy クラスがあり、これは .Net で使用できるものと同等であり、理論的には bcp コマンド ライン ユーティリティと同じくらい高速に動作するはずです。 https://msdn.microsoft.com/en-us/library/mt221490%28v=sql.110%29.aspx

于 2016-01-26T19:48:54.267 に答える
1

JDBC を使用してコードをカスタマイズできます。要件をサポートするフレームワークはありません。

于 2013-03-09T13:11:54.623 に答える