本篇效率最高!!!-在插入千万以上1G以上数据到数据库时。推荐细看。
详细思路请看springboot读取本地大文档1G目录导航-10
三层
1.controller层
@ApiOperation("insert接口-GG-Bach&SimbleSplitTxT添加数据")
@RequestMapping(value = "insertGGBachSimbleSplitTxT", method = RequestMethod.POST)
@ResponseBody
public void insertGGBachSimbleSplitTxTService(){
tsi.insertGGBachSimbleSplitTxTService();
}
2.service层
接口
void insertGGBachSimbleSplitTxTService();
实现类
@Override
public void insertGGBachSimbleSplitTxTService() {
/*1.设置batch手动提交*/
SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(
ExecutorType.BATCH, false);
/*2.通过session 获取mapper对象*/
tm = session.getMapper(TableMapper.class);
try {
/*3.1文件获取地址*/
File file = new File("D:/data/allCountries.txt");
/*3.2文件夹保存地址*/
File saveDir = new File("D:/data/splitDir");
/*4.1文件行数 获取方法会在工具类讲*/
long totalLens = 12052592;
/*4.2设置每个子文件最多行数*/
long eachLens = 1000000;
//1.先获取所有拆分好的子文件
ArrayList<File> alFile = ReadTxt.splitTxt(file,saveDir,totalLens,eachLens);
//2.然后遍历 分成两份 每份10万条数据调用之前的方法插入到数据库
for(int i = 0;i<alFile.size();i++){
//al存入的是一个子txt
List<Geoname> al = ReadTxt.txt2String(alFile.get(i));
int fen = al.size()/10000;
//将10万条分成100份 每份1000条(提交) 分批提交到数据库
for (int j = 1; j <= fen+1; j++) {
long time1 = System.currentTimeMillis();
//将1000条插入到数据库 k是al文件下标 小于遍历最大数1000行 小于al集合size
for(int k = (j-1)*10000;k<j*10000&&k<al.size();k++){
tm.insertTableSimble(al.get(k));
}
//手动每10000个一提交,提交后无法回滚
session.commit();
//清理缓存,防止溢出
session.clearCache();
long time2 = System.currentTimeMillis();
System.out.println("存入数据库第"+j+"次耗时:"+(time2-time1));
}
}
} catch (Exception e) {
//没有提交的数据可以回滚
session.rollback();
} finally {
session.close();
}
}
工具类
/*4读文档 拆分文档成100份 返回路径file组成的集合
*根据需求,直接调用静态方法start来执行操作
*参数:
* rows 为多少行一个文件 int 类型
* sourceFilePath 为源文件路径 String 类型
* targetDirectoryPath 为文件分割后存放的目标目录 String 类型
* ---分割后的文件名为索引号(从0开始)加'_'加源文件名,例如源文件名为test.txt,则分割后文件名为0_test.txt,以此类推
将文件按行分割
*/
/*将文件拆分 返回文件路径组成的集合*/
public static ArrayList<File> splitTxt(File sourceFile,File saveDir,long totalLens,long lens){
//0.创建路径组成的集合
ArrayList<File> alf = new ArrayList<>();
//1.获取文件路径,需要保存的文件路径,文件总行数,被拆分的子文件行数
try {
//2.获取文件
BufferedReader br = new BufferedReader(new FileReader(sourceFile));
//3.循环读取文件i---i+10000行数据拼接\r\n存入到StringBuilder中
long nowLen = 1;
//第一个循环 创建多少个文件
for(int i = 0;i<=totalLens/lens;i++){
Long time1 = System.currentTimeMillis();
//第二个循环获取行,存入StringBuilder
StringBuilder sb = new StringBuilder();
for(int j = 0;j<lens;j++){
nowLen = (j+1)+i*lens;
sb = sb.append(br.readLine()+"\r\n");
if(nowLen==totalLens){
break;
}
}
//创建文件并存入数据
File wfile = new File(saveDir.getAbsolutePath()+"/"+i+"_"+sourceFile.getName());
BufferedWriter bw = new BufferedWriter(new FileWriter(wfile));
bw.write(sb.toString());
bw.flush();
bw.close();
alf.add(wfile);
Long time2 = System.currentTimeMillis();
System.out.println("拆分出第"+i+"个文件所需时间为:"+(time2-time1));
}
br.close();
//4.将stringbuilder写到文档中
}catch (Exception e){
System.out.println("文件在拆分的时候报错!");
}
return alf;
}
// 3.3获取文件内容的总行数。
static long getTotalLines(File file) {
long lines = 0;
try{
FileReader in = new FileReader(file);
LineNumberReader reader = new LineNumberReader(in);
String s = reader.readLine();
while (s != null) {
lines++;
s = reader.readLine();
}
reader.close();
in.close();
}catch (Exception e){
System.out.println("读取文件总行数出错!");
}
return lines;
}
3.mapper层
接口
void insertTableSimble(Geoname g);
实现类
<insert id="insertTableSimble" parameterType="com.example.springboot6.bean.Geoname" >
insert into allCountries (geonameid,name,asciiname,alternatenames,latitude,longitude,feature_class,feature_code,country_code,cc2,admin1_code,admin2_code,admin3_code,admin4_code,population,elevation,dem,timezone,modification_date)
values (#{geonameid,jdbcType=INTEGER},#{name,jdbcType=VARCHAR},#{asciiname,jdbcType=VARCHAR},#{alternatenames,jdbcType=VARCHAR},#{latitude,jdbcType=DOUBLE},#{longitude,jdbcType=DOUBLE},#{featureClass,jdbcType=CHAR},#{featureCode,jdbcType=VARCHAR},#{countryCode,jdbcType=VARCHAR},#{cc2,jdbcType=VARCHAR},#{admin1Code,jdbcType=VARCHAR},#{admin2Code,jdbcType=VARCHAR},#{admin3Code,jdbcType=VARCHAR},#{admin4Code,jdbcType=VARCHAR},#{population,jdbcType=BIGINT},#{elevation,jdbcType=INTEGER},#{dem,jdbcType=INTEGER},#{timezone,jdbcType=VARCHAR},#{modificationDate,jdbcType=DATE})
</insert>
完毕!