您的位置:首页 > 数据库

jdbc批量插入,通过csv文件多数据拼一条sql执行。

2014-12-09 00:00 453 查看
因以后工作可能需要,写了一个小工具类 , 博客记录下。

原理是通过读取csv文件进行sql语句的拼串,将要插入的多数据拼成一条来执行,效率比多条执行要高很多。

测试了一下,10W条数据(简单的测试数据)用传统的PrepareStatement的addBatch()方法1000条执行一次,耗时7秒左右。

现在通过拼串的方法将1000条数据拼成一条sql 10W条下来用时1秒多。

工具的参数写的有点死,结合实际的时候需要改动。而且还有好多可以优化的地方。希望大家指正。

package db;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
* 利用csv文件拼一条sql语句进行数据库插入
*
* @author cuijk
* @date 2014-12-8
*
*/
public class SqlUtil {

private static String driver = "com.mysql.jdbc.Driver";
private static String url = "jdbc:mysql://localhost:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=utf-8";
private static String user = "root";
private static String pwd = "root";
private static String filePath = "d://test.csv";
// 读取文件时要用的字符编码
private static String charset = "UTF-8";
// sql前后缀
private static String preSql = "INSERT INTO users(username,pwd) VALUES ";
// 参数
private static String sufSql = "(?,?),";

public static void main(String[] args) {
int i = insert(driver, url, user, pwd, preSql, sufSql, filePath,
charset);
System.out.println(i);
}

/**
*
* @param driver
*            数据库驱动
*            <p>
*            com.mysql.jdbc.Driver
* @param url
*            数据库url
*            <p>
*            jdbc:mysql://localhost:3306/test
* @param user
*            用户名
* @param pwd
*            密码
* @param preSql
*            sql语句前缀
*            <p>
*            INSERT INTO users(username,pwd) VALUES
* @param sufSql
*            sql语句后缀
*            <p>
*            (?,?),
* @param filePath
*            文件路径
*            <p>
*            d://test.csv
* @param charset
*            读取文件时所用的编码
*            <p>
*            UTF-8
* @return
*
*/
public static int insert(String driver, String url, String user,
String pwd, String preSql, String sufSql, String filePath,
String charset) {

long start = System.currentTimeMillis();
StringBuilder sqlSb = null;
Connection conn = null;
BufferedReader br = null;
InputStreamReader isr = null;
PreparedStatement pstm = null;
int count = 0;
int total = 0;
try {
String line = "";
isr = new InputStreamReader(
new FileInputStream(new File(filePath)), charset);
br = new BufferedReader(isr);
// 获取非手动提交Connection
conn = getConnection(driver, url, user, pwd);
sqlSb = new StringBuilder(preSql);

List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList<String>();

while ((line = br.readLine()) != null) {
count++;
total++;
sqlSb.append(sufSql);

list1.add(line.substring(0, line.indexOf(",")));
list2.add(line.substring(line.indexOf(",") + 1, line.length()));

if (count >= 1000) {
// 去除sql最后的一个',';
sqlSb.delete(sqlSb.length() - 1, sqlSb.length());
pstm = conn.prepareStatement(sqlSb.toString());

// 填充占位符
for (int i = 0; i < count; i++) {
pstm.setString(i * 2 + 1, list1.get(i));
pstm.setString(i * 2 + 2, list2.get(i));
}

pstm.execute();// 执行一条sql语句
conn.commit();
System.out.println("处理 : " + count + "条记录。");

// 处理完1000条就清空一次
sqlSb = new StringBuilder(preSql);

count = 0;
list1.clear();
list2.clear();
}
}
if (count > 0) {
// 清理sql语句
sqlSb = new StringBuilder(preSql);

for (int i = 0; i < count; i++) {
sqlSb.append(sufSql);
}
// 删除最后一个','
sqlSb.delete(sqlSb.length() - 1, sqlSb.length());

pstm = conn.prepareStatement(sqlSb.toString());

for (int i = 0; i < count; i++) {
pstm.setString(i * 2 + 1, list1.get(i));
pstm.setString(i * 2 + 2, list2.get(i));
}

pstm.execute();
pstm.clearBatch();
System.out.println("处理 : " + count + "条数据");
conn.commit();
}
list1.clear();
list2.clear();

double time = ((double) (System.currentTimeMillis() - start)) / 1000;
System.out.println("处理完毕,共处理" + total + "条记录,花费 : " + time + "秒");
return total;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
if (isr != null) {
isr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
closeConn(conn);
}
return 0;
}

/**
* 获取链接,setAutoCommit(false),设置非自动提交
*
* @param dbDriver
* @param dbUrl
* @param dbUser
* @param dbPwd
* @return
* @throws InstantiationException
* @throws IllegalAccessException
* @throws ClassNotFoundException
* @throws SQLException
*/
private static Connection getConnection(String dbDriver, String dbUrl,
String dbUser, String dbPwd) throws InstantiationException,
IllegalAccessException, ClassNotFoundException, SQLException {

Class.forName(dbDriver).newInstance();
Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPwd);
conn.setAutoCommit(false);
return conn;

}

/**
* 关闭链接
*
* @param conn
*/
private static void closeConn(Connection conn) {

try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
System.out.println("连接未正常关闭");
}

}

}


另外附带一个 输出CSV文件的简单实现:

package io;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;

public class CSVUtil {

public static void main(String[] args) {
int count = 100054;
File file = new File("d://test.csv");
long s = System.currentTimeMillis();

List<String> dataList = new ArrayList<String>();
for (int i = 0; i < count; i++) {
dataList.add("测试一1,测试二2");
}

exportCsv(file, dataList);
dataList.clear();

double e = (double) System.currentTimeMillis();
System.out.println((e - s) / 1000);
}

public static boolean exportCsv(File file, List<String> dataList) {
boolean isSucess = false;
FileOutputStream out = null;
OutputStreamWriter osw = null;
BufferedWriter bw = null;
try {
out = new FileOutputStream(file);
osw = new OutputStreamWriter(out, "UTF-8");
bw = new BufferedWriter(osw);
if (dataList != null && !dataList.isEmpty()) {
for (String data : dataList) {
// 为文件加入bom信息头
bw.write(new String(new byte[] { (byte) 0xEF, (byte) 0xBB,
(byte) 0xBF }));
bw.write(new String(data.getBytes("UTF-8")));
bw.newLine();
}
bw.flush();
}
isSucess = true;
} catch (Exception e) {
isSucess = false;
} finally {
if (bw != null) {
try {
bw.close();
bw = null;
} catch (IOException e) {
e.printStackTrace();
}
}
if (osw != null) {
try {
osw.close();
osw = null;
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
out = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
return isSucess;
}

public static List<String> importCsv(File file) {
List<String> dataList = new ArrayList<String>();
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(file));
String line = "";
while ((line = br.readLine()) != null) {
dataList.add(line);
}
} catch (Exception e) {
} finally {
if (br != null) {
try {
br.close();
br = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
return dataList;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐