Csv导入数据至数据库

import java.sql.*;
import java.util.*;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.PreparedStatement;
import com.mysql.jdbc.ResultSetMetaData;
public class test {
private static final String DRIVER = "com.mysql.jdbc.Driver";
private static final String URL = "jdbc:mysql://localhost:3306/world?useUnicode=true&characterEncoding=utf-8";
private static final String USERNAME = "root";
private static final String PASSWORD = "root";
private static final String SQL = "SELECT * FROM ";// 数据库操作
static {
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
}
}
/**
* 获取数据库连接
*
* @return
*/
public static Connection getConnection() {
Connection conn = null;
try {
conn = (Connection) DriverManager.getConnection(URL, USERNAME, PASSWORD);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
/**
* 关闭数据库连接
* @param conn
*/
public static void closeConnection(Connection conn) {
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 用于注入参数
* @param data 参数
* @param n 不插入字段的个数
* @throws SQLException
*/
private static PreparedStatement excutePs(PreparedStatement pStemt, Connection conn, String sql, int length, String[] data, int n) throws SQLException {
// Connection conn = getConnection(); // 首先要获取连接,即连接到数据库
// PreparedStatement ps = null;
// 预处理SQL 防止注入
pStemt = (PreparedStatement) conn.prepareStatement(sql);
// 注入参数
for (int i = 0; i < length-n; i++) {
if("".equals(data[i+n])) {//mysql 5以上的版本插入时,如果是空值应该要写NULL
data[i+1] = null;
}
pStemt.setString(i + 1, data[i+n]);
}
return pStemt;
}
/**
* 添加数据
* @param tabName 表名
* @param fields 参数字段
* @param data 参数字段数据
*/
public static void insert(String tabName, String[] fields, String[] data) {
Connection conn = getConnection(); // 首先要获取连接,即连接到数据库
PreparedStatement pStemt = null;
try {
String sql = "insert into " + tabName + "(";
int length = fields.length;
int n = 0;//不插入字段的个数
for (int i = 0; i < length; i++) {
if("id".equals(fields[i])) {//id是主键,不插入
n++;
continue;
}
sql += fields[i];
// 防止最后一个,
if (i < length - 1) {
sql += ",";
}
}
sql += ") values(";
for (int i = 0; i < length - n; i++) {
sql += "?";
// 防止最后一个,
if (i < length - (n+1)) {
sql += ",";
}
}
sql += ");";
// System.out.println("添加数据的sql:" + sql);
// 预处理SQL 防止注入
pStemt = excutePs(pStemt,conn,sql, length, data,n);
// 执行
pStemt.executeUpdate();
} catch (SQLException e) {
System.out.println("添加数据失败" + e.getMessage());
} finally {
if (pStemt != null) {
try {
pStemt.close();
closeConnection(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
/**
* 批量添加数据
* @param tabName 表名
* @param fields 参数字段
* @param contentList 参数字段数据
*/
public static void plinsert(String tabName, String[] fields, List<String[]> contentList) {
Connection conn = getConnection(); // 首先要获取连接,即连接到数据库
PreparedStatement pStemt = null;
try {
//设置conn.setAutoCommit(false); 关闭事务自动提交 ,这一行必须加上
//最后在所有命令执行完之后再提交事务conn.commit();
conn.setAutoCommit(false);
String sql = "insert into " + tabName + "(";
int length = fields.length;
int n = 0;//不插入字段的个数
for (int i = 0; i < length; i++) {
if("id".equals(fields[i])) {//id是主键,不插入
n++;
continue;
}
sql += fields[i];
// 防止最后一个,
if (i < length - 1) {
sql += ",";
}
}
sql += ") values(";
for (int i = 0; i < length - n; i++) {
sql += "?";
// 防止最后一个,
if (i < length - (n+1)) {
sql += ",";
}
}
sql += ");";
System.out.println("添加数据的sql:" + sql);
pStemt = plexcutePs(pStemt,conn,sql, length, contentList,n);//批量插入方法
} catch (SQLException e) {
System.out.println("添加数据失败" + e.getMessage());
} finally {
if (pStemt != null) {
try {
pStemt.close();
closeConnection(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
/**
*注入参数
*/
private static PreparedStatement plexcutePs(PreparedStatement pStemt, Connection conn, String sql, int length, List<String[]> contentList, int n) throws SQLException {
int batchSize = 5000; //设置批量处理的数量
int j = 0;
// 预处理SQL 防止注入
pStemt = (PreparedStatement) conn.prepareStatement(sql);
// 注入参数
for(String[] data: contentList) {
for (int i = 0; i < length-n; i++) {
if("".equals(data[i+n])) {//mysql 5以上的版本插入时,如果是空值应该要写NULL
data[i+n] = null;
}
pStemt.setString(i + 1, data[i+n]);
}
pStemt.addBatch();
j++;
if(j % batchSize == 0) {
pStemt.executeBatch();//批量操作
conn.commit();
pStemt.clearBatch();//清除缓存
}
}
if(j % batchSize != 0) {
pStemt.executeBatch();
conn.commit();
pStemt.clearBatch();
}
return pStemt;
}
public static void main(String[] args) throws IOException {
String tabName = "tableName";//要插入数据的表名
CsvReader csvReader = new CsvReader("D:\\csv\\test.csv", ',', Charset.forName("GBK"));//Charset.forName("GBK")---与导出时一致
csvReader.setSafetySwitch(false);
//设置为false,可使每列的最大值超过100,000,解析器会使用大量内存
//不设置默认每列的最大值不可超过100,000
char delimiter = csvReader.getDelimiter(); // 获取用作列分隔符的字符
csvReader.readHeaders();
int headerNum = csvReader.getHeaderCount();// 获取上一次调用读入的表头数 readHeaders()
String[] headers = csvReader.getHeaders();// 以字符串数组的形式返回表头值
List<String[]> contentList = new ArrayList<>();
while (csvReader.readRecord()) {// 读取另一条记录
String[] contents = new String[headers.length];
int i = 0;
for (String header : headers) {//
String content = csvReader.get(header);// 获取 给定列 标题名称 的当前列值
contents[i] = content;
i++;
}
contentList.add(contents);
}
Long startTime = System.currentTimeMillis();
for (String[] data : contentList) {// 执行插入数据方法---传统方法,一条一条插入
DataBaseUtils.plinsert(tabName, headers, data);
}
plinsert(tabName, headers, contentList);// 批量执行插入数据方法
Long endTime = System.currentTimeMillis();
System.out.println("用时:" + (endTime - startTime)+"ms");
}
}

参考链接:
https://www.jb51.net/article/121530.htm
https://my.oschina.net/u/2930289/blog/1589704
https://blog.csdn.net/qy20115549/article/details/52699724
var code = “3a520254-5865-4862-9f38-8023df9ec3e1”

posted @   loooooop  阅读(6)  评论(0编辑  收藏  举报  
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示