がありjava PreparedStatementsとResultSets?
-
11-07-2019 - |
質問
を考慮するコード:
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.createStatement(myQueryString);
rs = ps.executeQuery();
// process the results...
} catch (java.sql.SQLException e) {
log.error("an error!", e);
throw new MyAppException("I'm sorry. Your query did not work.");
} finally {
ps.close();
rs.close();
}
上記にないコンパイルしているため、 PreparedStatement.close()
や ResultSet.close()
捨てる java.sql.SQLException
.いていただいておりまtry/catchブロックのfinally?又は移動の諸表のtry?はまぁいいんじゃない呼び出し圏?
解決
ファイルI / Oの場合、通常はtry / catchをfinallyブロックに追加します。ただし、finallyブロックから例外をスローしないように注意する必要があります。例外が発生すると、元の例外(存在する場合)が失われるためです。
データベース接続のクローズのより具体的な例については、この記事を参照してください。
>他のヒント
Java7のいずれもないあって明示的にも利用 自動的資源管理 保 資源 が閉まっている例外を適切に取扱います。例外処理の作品のようになります:
Exception in try | Exception in close | Result -----------------+--------------------+---------------------------------------- No | No | Continue normally No | Yes | Throw the close() exception Yes | No | Throw the exception from try block Yes | Yes | Add close() exception to main exception | | as "suppressed", throw main exception
今意いたしました。ですかコードのようになります:
private void doEverythingInOneSillyMethod(String key)
throws MyAppException
{
try (Connection db = ds.getConnection()) {
db.setReadOnly(true);
...
try (PreparedStatement ps = db.prepareStatement(...)) {
ps.setString(1, key);
...
try (ResultSet rs = ps.executeQuery()) {
...
}
}
} catch (SQLException ex) {
throw new MyAppException("Query failed.", ex);
}
}
前のJava7のでご利用入れ子の最後にブロックにより検査の参考のためのnullになります。
の例は、私のようになってい醜いに深くネストしたが、実際に、コードしょうがなくなるわけではありません接続を作成し、結果はすべて同じ方法しばしば、各レベルの営巣は通のリソースが別の方法を用いた工場としても資源です。このアプローチから例外がスローされる場合 close()
はマスクの例外からの try
ブロックです。ことを乗り越えることができると思うが、その結果としても汚コード、カスタム例外クラスを提供する"抑制"の例外チェーン現在のJava7.
Connection db = ds.getConnection();
try {
PreparedStatement ps = ...;
try {
ResultSet rs = ...
try {
...
}
finally {
rs.close();
}
}
finally {
ps.close();
}
}
finally {
db.close();
}
本当に自分のjdbcを手で回しているのなら、間違いなく面倒です。最後のclose()は、独自のtryキャッチでラップする必要がありますが、これは少なくともatいです。クローズをスキップすることはできませんが、接続がクローズされるとリソースがクリアされます(プールを使用している場合は、すぐに終了しない場合があります)。実際、フレームワーク(たとえば、休止状態)を使用してdbアクセスを管理する主なセールスポイントの1つは、接続と結果セットの処理を管理することです。
このような簡単なことができます。これにより、少なくとも混乱が隠され、何かを忘れないことが保証されます。
public static void close(ResultSet rs, Statement ps, Connection conn)
{
if (rs!=null)
{
try
{
rs.close();
}
catch(SQLException e)
{
logger.error("The result set cannot be closed.", e);
}
}
if (ps != null)
{
try
{
ps.close();
} catch (SQLException e)
{
logger.error("The statement cannot be closed.", e);
}
}
if (conn != null)
{
try
{
conn.close();
} catch (SQLException e)
{
logger.error("The data source connection cannot be closed.", e);
}
}
}
そして
finally {
close(rs, ps, null);
}
低レベルの例外管理のコーディングに時間を無駄にしないでください。Spring-JDBCのような高レベルのAPI、またはconnection / statement / rsオブジェクトのカスタムラッパーを使用して、乱雑なtry-catchに乗ったコードを隠してください。
また注意:
" Statementオブジェクトが閉じられると、現在のResultSetオブジェクト(存在する場合)も閉じられます。 "
http:// java.sun.com/j2se/1.5.0/docs/api/java/sql/Statement.html#close()
最終的に、まだ閉じられていない場合にのみ、PreparedStatementを閉じるだけで十分です。本当に細かくしたい場合は、PreparedStatementを閉じた後ではなく、最初にResultSetを閉じます(この例のいくつかの例のように、それを閉じると、例外が既に閉じられているため、実際に例外が保証されます)。
通常、null参照で何もしようとしないように注意するなど、このようなことを閉じることができるユーティリティメソッドがあります。
通常、 close()
が例外をスローした場合、実際には気にしないので、例外をログに記録して飲み込むだけです。 / code>。どちらの方法でも、呼び出しが簡単なユーティリティメソッドで行うことをお勧めします。多くの場所でこれを行う必要があります。
PreparedStatementのクローズに失敗した場合、現在のソリューションはResultSetをクローズしないことに注意してください。ネストされたfinallyブロックを使用することをお勧めします。
Java 7を使用している場合、 AutoCloseable (つまり、 PreparedStatement
、 Resultset
)
この質問は興味深いものです。 Java 7でResultSetを閉じる
これは古い質問ですが、誰かが答えを探している場合に備えて、javaにはtry-with-resouceソリューションがあります。
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
closeの呼び出しを省略しないでください。問題を引き起こす可能性があります。
最後にtry / catchブロックを追加することを好みます。
おそらく(単純ではあるが)古いやり方ですが、それでも機能します:
public class DatabaseTest {
private Connection conn;
private Statement st;
private ResultSet rs;
private PreparedStatement ps;
public DatabaseTest() {
// if needed
}
public String getSomethingFromDatabase(...) {
String something = null;
// code here
try {
// code here
} catch(SQLException se) {
se.printStackTrace();
} finally { // will always execute even after a return statement
closeDatabaseResources();
}
return something;
}
private void closeDatabaseResources() {
try {
if(conn != null) {
System.out.println("conn closed");
conn.close();
}
if(st != null) {
System.out.println("st closed");
st.close();
}
if(rs != null) {
System.out.println("rs closed");
rs.close();
}
if(ps != null) {
System.out.println("ps closed");
ps.close();
}
} catch(SQLException se) {
se.printStackTrace();
}
}
}
@ericksonの答えに基づいて、なぜこのような1つの try
ブロックでそれをしないのですか?
private void doEverythingInOneSillyMethod(String key) throws MyAppException
{
try (Connection db = ds.getConnection();
PreparedStatement ps = db.prepareStatement(...)) {
db.setReadOnly(true);
ps.setString(1, key);
ResultSet rs = ps.executeQuery()
...
} catch (SQLException ex) {
throw new MyAppException("Query failed.", ex);
}
}
ResultSet
は ResultSet
が自動的に閉じられるため、 try
ブロック内に ResultSet
オブジェクトを作成する必要はありません。 code> PreparedStatement オブジェクトは閉じられています。
ResultSetオブジェクトは、Statementオブジェクトが 生成されたものは閉じられ、再実行されるか、次の 複数の結果のシーケンスからの結果。
参照: https://docs.oracle .com / javase / 7 / docs / api / java / sql / ResultSet.html
focus finally節、
finally {
try {
rs.close();
ps.close();
} catch (Exception e) {
// Do something
}
}
2つのポイントを変更する必要があると思います。
まず、try&を使用しますわずかな節でもう一度キャッチします。
次に、ps.close()を実行する前にrs.close()を実行します。
fly1997@naver.com
これを使用します。
finally
{
if (ps != null) ps.close();
if (rs != null) rs.close();
}