Reputation: 842
Eclipse displays warning messages saying "Resource Leak, preparedstatement is not closed at following location"
To me it looks like finally block takes care of closing preparedstatement and rs object. Any idea why eclipse is still complaining on resource leak?
String ruleGrpId = null;
int finalRuleID = 0;
String saveRule1 = "INSERT INTO ..";
String saveRule2 = "INSERT INTO ";
String saveRule3 = "select ..._name = ?";
PreparedStatement preparedstatement = null;
ResultSet rs = null;
try {
if (objSomeRule.getRule() == 0) {
preparedstatement = con.prepareStatement(saveRule1);
preparedstatement.setString(1, ruleId);
preparedstatement.executeUpdate();
//Eclipse complains here
preparedstatement = con.prepareStatement(saveRule2);
preparedstatement.setInt(1, ruleID_2);
preparedstatement.setString(2, ruleID_3);
rs = preparedstatement.executeQuery();
if(rs.next()){
finalRuleID = rs.getInt(1);
}else{
//complains here
preparedstatement = con.prepareStatement(saveRule3);
preparedstatement.setString(1, ruleID_4);
//complains here
rs = preparedstatement.executeQuery();
if(rs.next()){
finalRuleID = rs.getInt("rulegroup_id");
}
}
objSomeRule.setRuleID(finalRuleID);
}
} finally {
if(preparedstatement != null){
preparedstatement.close();
}
if(rs != null){
rs.close();
}
}
return finalRuleID;
}
Upvotes: 0
Views: 4568
Reputation: 10127
You create 3 different instances of PreparedStatement
:
preparedstatement = con.prepareStatement(saveRule1);
preparedstatement = con.prepareStatement(saveRule2);
preparedstatement = con.prepareStatement(saveRule3);
Your variable preparedStatement
only holds the last one you opened,
and you no have no references to the others you opened before.
Therefore, in your finally
section you only close this one last PreparedStatement
:
preparedstatement.close();
A similar issue is with your ResultSet
s.
You create 2 instances, but you close only 1 of them.
Upvotes: 2
Reputation: 109547
The reuse of variables preparedStatement
and rs
prevents calling close()
on the old object values of the variables. Try-with-resources is a neat solutions as close()
is called automatically, even when an exception was thrown or a return executed in a deeply nested try.
String ruleGrpId = null;
int finalRuleID = 0;
String saveRule1 = "INSERT INTO ..";
String saveRule2 = "INSERT INTO ";
String saveRule3 = "select ..._name = ?";
if (objSomeRule.getRule() == 0) {
try (PreparedStatement ps1 = con.prepareStatement(saveRule1)) {
ps1.setString(1, ruleId);
ps1.executeUpdate();
}
try (PreparedStatement ps2 = con.prepareStatement(saveRule2)) {
ps2.setInt(1, ruleID_2);
ps2.setString(2, ruleID_3);
try (ResultSet rs2 = ps2.executeQuery()) {
if (rs2.next()) {
finalRuleID = rs2.getInt(1);
} else {
try (Preparedstatement ps3 = con.prepareStatement(saveRule3)) {
ps3.setString(1, ruleID_4);
//complains here
try (ResultSet rs3 = ps3.executeQuery()) {
if (rs3.next()) {
finalRuleID = rs3.getInt("rulegroup_id");
}
}
}
}
}
objSomeRule.setRuleID(finalRuleID);
}
}
Should the last SELECT query intend to retrieve the AUTOINCREMENT ID of a prior INSERT, then this can be done safer (multi-user) and better using getGeneratedKeys
Upvotes: 3
Reputation: 31397
So, you are saying when there are no record create another preparedStatement.
if(rs.next())
{
finalRuleID = rs.getInt(1);
}
else
{
//close here first
if(preparedstatement != null)
{
preparedstatement.close();
}
if(rs != null){
rs.close();
}
preparedstatement = con.prepareStatement(saveRule3);
// your code
But, you haven't closed the previous one. I'm not exactly sure, why are you doing that, but, assuming you need to do this. Then, you should close the previous one first.
Upvotes: 2