2023年8月3日发(作者:)

jdbc-批量插⼊、批量删除、批量更新⼀、JDBC的批量插⼊ JDBC批量插⼊主要⽤于数据导⼊和⽇志记录因为⽇志⼀般都是先写在⽂件下的等。 我⽤Mysql5.1.5的JDBC driver 分别对三种⽐较常⽤的⽅法做了测试 ⽅法⼀,使⽤PreparedStatement加批量的⽅法 Java代码

try{

e("");

conn = nection(o_url, userName,password);

oCommit(false);

String sql = "INSERT adlogs(ip,website,yyyymmdd,hour,object_id)VALUES(?,?,?,?,?)";

PreparedStatement prest =eStatement(sql,_SCROLL_SENSITIVE,_READ_ONLY);

for(int x = 0; x < size;x++){

ing(1,"192.168.1.1");

ing(2,"localhost");

ing(3,"20081009");

(4,8);

ing(5,"11111111");

ch();

}

eBatch();

();

();

} catch (SQLException ex){

ger(e()).log(, null,ex);

} catch (ClassNotFoundException ex){

ger(e()).log(, null,ex);

}

说明下在建Statement的时候,后⾯两个参数的意义:第⼀个参数指定 ResultSet 的类型。其选项有:TYPE_FORWARD_ONLY:缺省类型。只允许向前访问⼀次,并且不会受到其他⽤户对该数据库所作更改的影响。TYPE_SCROLL_INSENSITIVE:允许在列表中向前或向后移动,甚⾄可以进⾏特定定位,例如移⾄列表中的第四个记录或者从当前位置向后移动两个记录。不会受到其他⽤户对该数据库所作更改的影响。TYPE_SCROLL_SENSITIVE:象 TYPE_SCROLL_INSENSITIVE⼀样,允许在记录中定位。这种类型受到其他⽤户所作更改的影响。如果⽤户在执⾏完查询之后删除⼀个记录,那个记录将从 ResultSet中消失。类似的,对数据值的更改

也将反映在 ResultSet 中。第⼆个参数设置 ResultSet 的并发性,该参数确定是否可以更新 ResultSet。其选项有:CONCUR_READ_ONLY:这是缺省值,指定不可以更新ResultSet CONCUR_UPDATABLE:指定可以更新 ResultSet⽅法⼆ 使⽤Statement加批量的⽅法Java代码

oCommit(false);

Statement stmt =Statement(_SCROLL_SENSITIVE,_READ_ONLY);

for(int x = 0; x < size;x++){

ch("INSERT INTOadlogs(ip,website,yyyymmdd,hour,object_id) VALUES('192.168.1.3','localhost','20081009',8,'23123')");

}

eBatch();

();

⽅法三:直接使⽤StatementJava代码oCommit(false);

Statement stmt =Statement(_SCROLL_SENSITIVE,

_READ_ONLY);

for(int x = 0; x < size;x++){

e("INSERT INTOadlogs(ip,website,yyyymmdd,hour,object_id) VALUES('192.168.1.3','localhost','20081009',8,'23123')");

}

();

使⽤上述⽅法分别插⼊10万条数据的平均测试时间为:⽅法⼀:17.844s⽅法⼆:18.421s⽅法三:16.359s

可以看出JDBC的batch语句插⼊不但没有性能提升,反⽽⽐没有⽤batch的时候要慢,当然这可能跟JDBC具体驱动的实现⽅法有关。附件中是我测试代码,可以⽤来在⾃⼰电脑上跑⼀下。在执⾏批量插⼊的时候最主要的是将⾃动提交取消,这样不管是否⽤JDBC的batch语法应该都没有关系。Java代码oCommit(false)

⼆、JDBC的批量更新 由于阿堂在原来的⽼项⽬中,⽤jdbc操作时,⽤到了jdbc的批量操作,加上前段时间看《疯狂java讲义》时,也看到李刚作者的相关介绍。考虑还是会有⼈要⽤到jdbc的操作的,所以,阿堂还是把它整⼀下,就成了下⾯的⽂字了。⽤JDBC的DML语句时(insert,delete,update),我们可能可能需要同时某⼏个表都要进⾏DML操作,⽐如,当我们对A表插⼊的时候,同时也要对B表插⼊相关的记录,还要同时更新C表的关联记录,这样就会涉及到三条DML的sql语句,如果不⽤批量更新功能的话,我们就得单独去处理,效率相对就要低些了。。使⽤批量更新时,多条sql语句将会被作为⼀批操作被同时收集,并同时提交。值得注意的是,批量更新必须得到底层数据库的⽀持,可能通过DatabaseMetaData的supportBatchUpdates⽅法来查看底层数据库是否⽀持批量更新//conn是Connection的类型 DatabaseMetaDatadbmd=aData();//若a为true则意味着该数据是⽀持批量更新的boolean a=tsBatchUpdates();

为了保证批量更新的操作可以正确处理错务,必须把批量更新的操作视为单个事务,如果批理更新在执⾏过程中失败,则让事务回滚到操作开始之前的状态。为了达到这种效果,程序应该在开始批量操作之前先关闭⾃动提交,然后开始收集更新语句,当批量操作执⾏结束后,提交事务,并恢复之前的⾃动提交模式 具体如下代码⽚断所⽰ try { //保存当前⾃动提交模式 booleanautoCommit=oCommit(); //关闭⾃动提交 oCommit(false); //使⽤Statement同时收集多条sql语句 ch(insert_sql1); ch(insert_sql2); ch(update_sql3); .. //同时提交所有的sql语句 eBatch(); //提交修改 (); oCommit(autoCommit); } catch(Exception e) { tackTrace() ck();

}

附:需要说明的⼀点是,如果是addBatch()⽅法中加了select查询语句,程序将直接出现错务的

这个⼜是⼀种⽅法批量进⾏更新。但是我认为上⾯那个⽅法不错tx=ransaction();Connection con = tion();PreparedStatement stmt = eStatement( "update CUSTOMERS set AGE=AGE+1 where AGE>0");Update();();

三、JDBC批量删除String sql="delete from table where idin(0";

String id[]=要删除的ID数组;

for(int i=0;i<;i++)

{

sql+=","+id[i];

}

sql+=")";

PreparedStatementps=eStatement(sql);

e();

public void deleteBat(Integer[] catNo){

try {

Connection con=tance().getCon();

String sql="delete from cat where catno=?";

oCommit(false);

PreparedStatement ps=eStatement(sql);

for (Integer in : catNo) {

(1, in);

ch();

}

int[] result=eBatch();

();

for (int i : result) {

n(i);

}

} catch (ClassNotFoundException e) {

tackTrace();

} catch (SQLException e) {

tackTrace();

}

2023年8月3日发(作者:)

jdbc-批量插⼊、批量删除、批量更新⼀、JDBC的批量插⼊ JDBC批量插⼊主要⽤于数据导⼊和⽇志记录因为⽇志⼀般都是先写在⽂件下的等。 我⽤Mysql5.1.5的JDBC driver 分别对三种⽐较常⽤的⽅法做了测试 ⽅法⼀,使⽤PreparedStatement加批量的⽅法 Java代码

try{

e("");

conn = nection(o_url, userName,password);

oCommit(false);

String sql = "INSERT adlogs(ip,website,yyyymmdd,hour,object_id)VALUES(?,?,?,?,?)";

PreparedStatement prest =eStatement(sql,_SCROLL_SENSITIVE,_READ_ONLY);

for(int x = 0; x < size;x++){

ing(1,"192.168.1.1");

ing(2,"localhost");

ing(3,"20081009");

(4,8);

ing(5,"11111111");

ch();

}

eBatch();

();

();

} catch (SQLException ex){

ger(e()).log(, null,ex);

} catch (ClassNotFoundException ex){

ger(e()).log(, null,ex);

}

说明下在建Statement的时候,后⾯两个参数的意义:第⼀个参数指定 ResultSet 的类型。其选项有:TYPE_FORWARD_ONLY:缺省类型。只允许向前访问⼀次,并且不会受到其他⽤户对该数据库所作更改的影响。TYPE_SCROLL_INSENSITIVE:允许在列表中向前或向后移动,甚⾄可以进⾏特定定位,例如移⾄列表中的第四个记录或者从当前位置向后移动两个记录。不会受到其他⽤户对该数据库所作更改的影响。TYPE_SCROLL_SENSITIVE:象 TYPE_SCROLL_INSENSITIVE⼀样,允许在记录中定位。这种类型受到其他⽤户所作更改的影响。如果⽤户在执⾏完查询之后删除⼀个记录,那个记录将从 ResultSet中消失。类似的,对数据值的更改

也将反映在 ResultSet 中。第⼆个参数设置 ResultSet 的并发性,该参数确定是否可以更新 ResultSet。其选项有:CONCUR_READ_ONLY:这是缺省值,指定不可以更新ResultSet CONCUR_UPDATABLE:指定可以更新 ResultSet⽅法⼆ 使⽤Statement加批量的⽅法Java代码

oCommit(false);

Statement stmt =Statement(_SCROLL_SENSITIVE,_READ_ONLY);

for(int x = 0; x < size;x++){

ch("INSERT INTOadlogs(ip,website,yyyymmdd,hour,object_id) VALUES('192.168.1.3','localhost','20081009',8,'23123')");

}

eBatch();

();

⽅法三:直接使⽤StatementJava代码oCommit(false);

Statement stmt =Statement(_SCROLL_SENSITIVE,

_READ_ONLY);

for(int x = 0; x < size;x++){

e("INSERT INTOadlogs(ip,website,yyyymmdd,hour,object_id) VALUES('192.168.1.3','localhost','20081009',8,'23123')");

}

();

使⽤上述⽅法分别插⼊10万条数据的平均测试时间为:⽅法⼀:17.844s⽅法⼆:18.421s⽅法三:16.359s

可以看出JDBC的batch语句插⼊不但没有性能提升,反⽽⽐没有⽤batch的时候要慢,当然这可能跟JDBC具体驱动的实现⽅法有关。附件中是我测试代码,可以⽤来在⾃⼰电脑上跑⼀下。在执⾏批量插⼊的时候最主要的是将⾃动提交取消,这样不管是否⽤JDBC的batch语法应该都没有关系。Java代码oCommit(false)

⼆、JDBC的批量更新 由于阿堂在原来的⽼项⽬中,⽤jdbc操作时,⽤到了jdbc的批量操作,加上前段时间看《疯狂java讲义》时,也看到李刚作者的相关介绍。考虑还是会有⼈要⽤到jdbc的操作的,所以,阿堂还是把它整⼀下,就成了下⾯的⽂字了。⽤JDBC的DML语句时(insert,delete,update),我们可能可能需要同时某⼏个表都要进⾏DML操作,⽐如,当我们对A表插⼊的时候,同时也要对B表插⼊相关的记录,还要同时更新C表的关联记录,这样就会涉及到三条DML的sql语句,如果不⽤批量更新功能的话,我们就得单独去处理,效率相对就要低些了。。使⽤批量更新时,多条sql语句将会被作为⼀批操作被同时收集,并同时提交。值得注意的是,批量更新必须得到底层数据库的⽀持,可能通过DatabaseMetaData的supportBatchUpdates⽅法来查看底层数据库是否⽀持批量更新//conn是Connection的类型 DatabaseMetaDatadbmd=aData();//若a为true则意味着该数据是⽀持批量更新的boolean a=tsBatchUpdates();

为了保证批量更新的操作可以正确处理错务,必须把批量更新的操作视为单个事务,如果批理更新在执⾏过程中失败,则让事务回滚到操作开始之前的状态。为了达到这种效果,程序应该在开始批量操作之前先关闭⾃动提交,然后开始收集更新语句,当批量操作执⾏结束后,提交事务,并恢复之前的⾃动提交模式 具体如下代码⽚断所⽰ try { //保存当前⾃动提交模式 booleanautoCommit=oCommit(); //关闭⾃动提交 oCommit(false); //使⽤Statement同时收集多条sql语句 ch(insert_sql1); ch(insert_sql2); ch(update_sql3); .. //同时提交所有的sql语句 eBatch(); //提交修改 (); oCommit(autoCommit); } catch(Exception e) { tackTrace() ck();

}

附:需要说明的⼀点是,如果是addBatch()⽅法中加了select查询语句,程序将直接出现错务的

这个⼜是⼀种⽅法批量进⾏更新。但是我认为上⾯那个⽅法不错tx=ransaction();Connection con = tion();PreparedStatement stmt = eStatement( "update CUSTOMERS set AGE=AGE+1 where AGE>0");Update();();

三、JDBC批量删除String sql="delete from table where idin(0";

String id[]=要删除的ID数组;

for(int i=0;i<;i++)

{

sql+=","+id[i];

}

sql+=")";

PreparedStatementps=eStatement(sql);

e();

public void deleteBat(Integer[] catNo){

try {

Connection con=tance().getCon();

String sql="delete from cat where catno=?";

oCommit(false);

PreparedStatement ps=eStatement(sql);

for (Integer in : catNo) {

(1, in);

ch();

}

int[] result=eBatch();

();

for (int i : result) {

n(i);

}

} catch (ClassNotFoundException e) {

tackTrace();

} catch (SQLException e) {

tackTrace();

}