如何集成创建/接收连接,查询数据库以及可能使用Java 7的自动资源管理(try-with-resources语句)处理结果的常用JDBC习惯用法?(教程)
在Java 7之前,通常的模式是这样的:
Connection con = null;
PreparedStatement prep = null;
try{
con = getConnection();
prep = prep.prepareStatement("Update ...");
...
con.commit();
}
catch (SQLException e){
con.rollback();
throw e;
}
finally{
if (prep != null)
prep.close();
if (con != null)
con.close();
}
Run Code Online (Sandbox Code Playgroud)
使用Java 7,您可以选择:
try(Connection con = getConnection(); PreparedStatement prep = con.prepareConnection("Update ..."){
...
con.commit();
}
Run Code Online (Sandbox Code Playgroud)
这将关闭Connection和PreparedStatement,但滚动呢?我无法添加包含回滚的catch子句,因为该连接仅在try块中可用.
你还在try块之外定义连接吗?这里的最佳做法是什么,尤其是在使用连接池的情况下?
我想知道在try-with-resources块中放置一个return语句是否会阻止资源自动关闭.
try(Connection conn = ...) {
return conn.createStatement().execute("...");
}
Run Code Online (Sandbox Code Playgroud)
如果我写这样的东西将关闭连接?在Oracle文档中,声明:
try-with-resources语句确保在语句结束时关闭每个资源.
如果由于返回语句而从未到达语句的结尾会发生什么?
在Java 7的try-with-resources中,我不知道finally块和自动关闭发生了哪个顺序.订单是什么?
BaseResource b = new BaseResource(); // not auto-closeable; must be stop'ed
try(AdvancedResource a = new AdvancedResource(b)) {
}
finally {
b.stop(); // will this happen before or after a.close()?
}
Run Code Online (Sandbox Code Playgroud) 为什么在没有Catch或Finally的情况下编写Try,如下例所示?
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
/* TODO output your page here. You may use following sample code. */
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet tryse</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Servlet tryse at " + request.getContextPath() + "</h1>");
out.println("</body>");
out.println("</html>");
}
}
Run Code Online (Sandbox Code Playgroud) 我一直在看代码,我已经看过尝试资源.之前我使用过标准的try-catch语句,看起来它们做同样的事情.所以我的问题是Try With Resources vs Try-Catch 它们之间有什么区别,哪个更好.
这是资源的尝试:
objects jar = new objects("brand");
objects can= new objects("brand");
try (FileOutputStream outStream = new FileOutputStream("people.bin")){
ObjectOutputStream stream = new ObjectOutputStream(outStream);
stream.writeObject(jar);
stream.writeObject(can);
stream.close();
} catch(FileNotFoundException e) {
System.out.println("sorry it didn't work out");
} catch(IOException f) {
System.out.println("sorry it didn't work out");
}
Run Code Online (Sandbox Code Playgroud) 是否可以忽略使用try-with-resources语句关闭资源时抛出的异常?
例:
class MyResource implements AutoCloseable{
@Override
public void close() throws Exception {
throw new Exception("Could not close");
}
public void read() throws Exception{
}
}
//this method prints an exception "Could not close"
//I want to ignore it
public static void test(){
try(MyResource r = new MyResource()){
r.read();
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
}
Run Code Online (Sandbox Code Playgroud)
或者我应该继续关闭finally?
public static void test2(){
MyResource r = null;
try {
r.read();
}
finally{
if(r!=null){
try {
r.close(); …Run Code Online (Sandbox Code Playgroud) 我读到catchtry-with-resources 中的块是可选的.我尝试Connection在try-with-resources块中创建一个对象,没有后续catch块,只是为了从eclipse中获取编译器错误:" SQLException自动close()调用引发的未处理异常类型."
由于可以在try-with-resources中使用的每个资源都实现AutoCloseable,因此在调用close()方法时可能抛出异常,我不明白该catch子句是如何可选的,因为它不允许我跳过捕获异常close().
是否有一些特殊要求,具体实现AutoCloseable不直接声明其close()方法中抛出的任何异常?(如覆盖AutoCloseable的close() throws Exception一个close()不抛出任何异常)?
..或者这可能只是一个日食问题?
编辑:这是仍然触发问题的最简单的代码片段:
try (Connection con = dataSource.getConnection()) {
/*...*/
}
Run Code Online (Sandbox Code Playgroud)
关于这是否与使用JNDI数据源有关的想法?
提前致谢.
这是我关于SO的第一个问题,我很困惑,还没有类似的问题!
所以问题是:
为什么不尝试使用资源来处理字段变量?
换句话说:为什么我总是需要一个局部变量呢?
这里有一些示例代码:
public class FileWriteTest {
public FileWriter file;
public void workingDemo() {
try(FileWriter file = new FileWriter(new File("someFilePath")) {
// do something
} catch (IOException e) {
e.printStackTrace();
}
}
public void notWorkingDemo() {
file = null;
try(file = new FileWriter(new File("someFilePath")) {
// do something
} catch (IOException e) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
愿任何人解释我为什么有这个约定?
我正在创作一个java库.一些旨在由库用户使用的类保存本机系统资源(通过JNI).我想确保用户"处置"这些对象,因为它们很重,并且在测试套件中它们可能导致测试用例之间的泄漏(例如,我需要确保TearDown将丢弃).为此我使Java类实现了AutoCloseable,但这似乎不够,或者我没有正确使用它:
我不知道如何使用try-with-resources在测试的情况下(我使用的语句JUnit5有Mockito),在"资源"是不是短命的-这是测试夹具的一部分.
像往常一样勤奋,我尝试finalize()在那里实现和测试闭包,但事实finalize()证明甚至没有调用(Java10).这也被标记为已弃用,我确信这个想法不会受到诟病.
这是怎么做到的?要清楚,如果他们不调用close()我的对象,我希望应用程序的测试(使用我的库)失败.
编辑:添加一些代码,如果它有帮助.它并不多,但这正是我想要做的.
@SuppressWarnings("deprecation") // finalize() provided just to assert closure (deprecated starting Java 9)
@Override
protected final void finalize() throws Throwable {
if (nativeHandle_ != 0) {
// TODO finalizer is never called, how to assert that close() gets called?
throw new AssertionError("close() was not called; native object leaking");
}
}
Run Code Online (Sandbox Code Playgroud)
编辑2,赏金的结果感谢所有的回复,一半的赏金被自动授予.我的结论是,对于我的情况,最好尝试解决方案Cleaner.但是看起来,虽然已经注册,但是不会调用清理操作.我在这里问了一个跟进问题.
未能调用shutdown()线程执行程序将导致永不终止的应用程序.关闭ExecutorService的最佳做法是:
ExecutorService service = null;
try {
service = Executors.newSingleThreadExecutor();
// add tasks to thread executor
…
} finally {
if (service != null) service.shutdown();
}
Run Code Online (Sandbox Code Playgroud)
由于Java知道try-with-resources概念,如果我们能做到这一点会不会很好?
try (service = Executors.newSingleThreadExecutor())
{
// add tasks to thread executor
…
}
Run Code Online (Sandbox Code Playgroud)