Основная проблема заключается в том, что в вашем коде происходит исключение, но блок try / catch перехватывает его и молча проглатывает. Хотя может быть заманчиво перехватывать и глотать исключения, правда заключается в том, что они всегда вызывают больше проблем, чем решают, и ключевая концепция обработки исключений - НЕ обрабатывать их: просто поместите объявление throws
и позвольте приложению cra sh.
Затем у вас возникают другие возможные побочные проблемы в зависимости от того, как Connection
был получен в первую очередь, например, тот факт, что вы никогда не закрываете PreparedStatement
и ResultSet
(если соединение закрыто, они также закрыты ... но если соединение возвращается в пул, то они никогда не будут закрыты).
В общем, приведенный выше код имеет тенденцию упаковывать слишком много функциональности в одном метод и может быстро выйти из-под контроля, поэтому вы можете разделить его на более мелкие куски с четкими индивидуальными обязанностями. будь то из соображений максимальной производительности или из-за отсутствия опыта. Обычно в веб-приложениях, использующих среду Spring, это решается с помощью JdbcTemplate
, но я не могу предположить, что вы используете Spring, поэтому я не буду здесь показывать его использование.
Как минимум, я бы измените ваш код примерно следующим образом:
public boolean sendOffer(Sales sell) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = cu.getConnection();
ps = prepareInsertOfferStatement(sell, conn);
ps.executeUpdate();
rs = ps.getGeneratedKeys();
sell.setID(extractKey(rs));
conn.commit();
log.trace("success");
return true;
}
catch(Exception ex) {
log.error(ex); // this is actually probably bad. Consider putting a throws declaration and get rid of this catch
return false;
}
finally {
closeQuietly(rs, ps, conn);
}
}
private void closeQuietly(AutoCloseable... objs) {
for(AutoCloseable obj : objs) {
try {
obj.close();
} catch (SQLException e) {
// this is usually mostly safe to ignore. Maybe log a warning somewhere
}
}
}
private PreparedStatement prepareInsertOfferStatement(Sales sell, Connection conn) throws SQLException {
String sql = "INSERT INTO sales (offer_amount, offer_who, car_id) values(?,?,?)";
String[] keys= {"ID"};
PreparedStatement ps = conn.prepareStatement(sql,keys);
ps.setInt(1, sell.getOfferAmount());
ps.setInt(2, sell.getOwnerID()); //foreign key
ps.setInt(3, sell.getCarID()); // foreign key
return ps;
}
private int extractKey(ResultSet rs) throws SQLException {
if(rs.next()) {
return rs.getInt(1);
}
else {
throw new Exception("The statement did not return any generated key.");
}
}
Как видите, он не короче, но обязанности более понятны, и все объекты соответственно закрыты. Кроме того, он дает вам хорошие многократно используемые примитивы для закрытия соединений и связанных объектов, а также для извлечения ключа из других вставок, которые вы захотите сделать. Дальнейшие абстракции позволят вам получить больше примитивов, но я думаю, что этого достаточно, чтобы вы поняли суть этого.