问题描述
下面是我使用Prepared Statement在Oracle数据库中插入multiple records( around 5000-7000)
的代码.
Below is the code which I am using to insert multiple records( around 5000-7000)
in the Oracle Database using Prepared Statement.
我目前的工作方式很好吗?还是可以使用某些batch thing
来进一步改善?
The way I am doing currently is good? Or it can be improve more using some batch thing
?
pstatement = db_connection.prepareStatement(PDSLnPConstants.UPSERT_SQL);
for (Entry<Integer, LinkedHashMap<Integer, String>> entry : MAPPING.entrySet()) {
pstatement.setInt(1, entry.getKey());
pstatement.setString(2, entry.getValue().get(LnPConstants.CGUID_ID));
pstatement.setString(3, entry.getValue().get(LnPConstants.PGUID_ID));
pstatement.setString(4, entry.getValue().get(LnPConstants.SGUID_ID));
pstatement.setString(5, entry.getValue().get(LnPConstants.UID_ID));
pstatement.setString(6, entry.getValue().get(LnPConstants.ULOC_ID));
pstatement.setString(7, entry.getValue().get(LnPConstants.SLOC_ID));
pstatement.setString(8, entry.getValue().get(LnPConstants.PLOC_ID));
pstatement.setString(9, entry.getValue().get(LnPConstants.ALOC_ID));
pstatement.setString(10, entry.getValue().get(LnPConstants.SITE_ID));
pstatement.executeUpdate();
pstatement.clearParameters();
}
我正在使用的重复代码:-
public void runNextCommand() {
Connection db_connection = null;
PreparedStatement pstatement = null;
int batchLimit = 1000;
boolean autoCommit = false;
try {
db_connection = getDBConnection();
autoCommit = db_connection.getAutoCommit();
db_connection.setAutoCommit(false); //Turn off autoCommit
pstatement = db_connection.prepareStatement(LnPConstants.UPSERT_SQL); // create a statement
for (Entry<Integer, LinkedHashMap<Integer, String>> entry : GUID_ID_MAPPING.entrySet()) {
pstatement.setInt(1, entry.getKey());
pstatement.setString(2, entry.getValue().get(LnPConstants.CGUID_ID));
pstatement.setString(3, entry.getValue().get(LnPConstants.PGUID_ID));
pstatement.setString(4, entry.getValue().get(LnPConstants.SGUID_ID));
pstatement.setString(5, entry.getValue().get(LnPConstants.UID_ID));
pstatement.setString(6, entry.getValue().get(LnPConstants.ULOC_ID));
pstatement.setString(7, entry.getValue().get(LnPConstants.SLOC_ID));
pstatement.setString(8, entry.getValue().get(LnPConstants.PLOC_ID));
pstatement.setString(9, entry.getValue().get(LnPConstants.ALOC_ID));
pstatement.setString(10, entry.getValue().get(LnPConstants.SITE_ID));
pstatement.addBatch();
batchLimit--;
if(batchLimit == 0){
pstatement.executeBatch();
pstatement.clearBatch();
batchLimit = 1000;
}
pstatement.clearParameters();
}
} catch (SQLException e) {
getLogger().log(LogLevel.ERROR, e);
} finally {
try {
pstatement.executeBatch();
db_connection.commit();
db_connection.setAutoCommit(autoCommit);
} catch (SQLException e1) {
getLogger().log(LogLevel.ERROR, e1.getMessage(), e1.fillInStackTrace());
}
if (pstatement != null) {
try {
pstatement.close();
pstatement = null;
} catch (SQLException e) {
getLogger().log(LogLevel.ERROR, e.getMessage(), e.fillInStackTrace());
}
}
if (db_connection!= null) {
try {
db_connection.close();
db_connection = null;
} catch (SQLException e) {
getLogger().log(LogLevel.ERROR, e.getMessage(), e.fillInStackTrace());
}
}
}
}
推荐答案
您可以考虑使用 addBatch()
并一次性执行语句的后退.另外,正如@pst在您的问题中所述,请考虑使用trasaction
.
您的操作方式如下:
boolean autoCommit = connection.getAutoCommit();
try{
connection.setAutoCommit(false //Turn off autoCommit
pstatement = db_connection.prepareStatement(PDSLnPConstants.UPSERT_SQL);
int batchLimit = 1000;
try{
for (Entry<Integer, LinkedHashMap<Integer, String>> entry : MAPPING.entrySet()) {
pstatement.setInt(1, entry.getKey());
pstatement.setString(2, entry.getValue().get(LnPConstants.CGUID_ID));
pstatement.setString(3, entry.getValue().get(LnPConstants.PGUID_ID));
pstatement.setString(4, entry.getValue().get(LnPConstants.SGUID_ID));
pstatement.setString(5, entry.getValue().get(LnPConstants.UID_ID));
pstatement.setString(6, entry.getValue().get(LnPConstants.ULOC_ID));
pstatement.setString(7, entry.getValue().get(LnPConstants.SLOC_ID));
pstatement.setString(8, entry.getValue().get(LnPConstants.PLOC_ID));
pstatement.setString(9, entry.getValue().get(LnPConstants.ALOC_ID));
pstatement.setString(10, entry.getValue().get(LnPConstants.SITE_ID));
pstatement.addBatch();
batchLimit--;
if(batchLimit == 0){
pstatement.executeBatch();
pstatement.clearBatch
batchLimit = 1000;
}
pstatement.clearParameters();
}
}finally{
//for the remaining ones
pstatement.executeBatch();
//commit your updates
connection.commit();
}
}finally{
connection.setAutoCommit(autoCommit);
}
此想法是为批处理更新设置一个限制,并且仅在达到特定限制时才执行数据库更新.这样,您就可以将数据库调用限制为定义的每个batchLimit
一次.这样会更快.
The idea is to set a limit for batch updates and execute a database update only when you reach a particular limit. This way you're limiting a database call to once every batchLimit
that you've defined. This way it would be faster.
还要注意transaction
,我刚刚展示了commit
的使用方式和时间.这可能并非始终是commit
的正确点,因为此决定将基于您的要求.如果发生异常,您可能还想执行rollback
.因此,由您决定.
Also note for the transaction
, I've just shown how and when to commit
. This might not always be the correct point to commit
because this decision would be based on your requirement. You might also want to perform a rollback
in case of an exception. So it's upto you to decide.
看看使用事务" 教程来更好地了解如何使用transaction
.
Have a look at "Using Transaction" tutorial to get a better picture of how to use transaction
.
这篇关于有效地多次使用准备好的语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!