通过跨多个私有方法使用 JDBC 事务存储复杂对象会导致代码过载

Storing complicated object by using JDBC transactions across multiple private method cause to overloaded code

我正在使用 jdbc 交易,如下所述:JDBC Transaction example 来存储复杂的对象及其关系。例如,为了存储我调用 public "general method" 的汽车,它需要存储车轮、发动机、汽车本身等……它将这些任务委托给私有方法,并向其传递连接。如果在某个步骤出现问题,抛出的异常将被 public 方法捕获并执行回滚。

例如:

public boolean saveCar(Car car){
   Connection con = null;
   try{
        con = ....//get connection
        con.setAutoCommit(false);

        storeCar(car, con);
        storeWheels(car, con);
        storeEngine(car, con);

        con.commit();
   } catch(Exception e){
       e.printStackTrace();
       con.rollback();
   } finally {
      con.close();
   }

}


private void storeWheels(Car car, Connection con) throws Exception{
    String sql = "...";
    PreparedStatement ps = con.prepareStatement(sql);
    ps.executeUpdate;
}

但我也需要关闭 PreparedStatement。它应该在 finally 子句中关闭,所以我必须这样写我的私有方法:

private void storeWheels(Car car, Connection con) throws Exception{
        String sql = "...";
        PreparedStatement ps = null;
        try{
           ps = con.prepareStatement(sql);
           ps.executeUpdate;
        } catch (Exception e) {
            throw new Exception("Something went wrong");
        } finally {
            ps.close();
        }

    }

太多 try-catch 它使我的代码容易出错并且超载。从 catch 块中抛出 Exception 也不好看。我的问题是如何能够或是否有可能像我描述的那样委派这些任务,并避免在每个私有方法中出现不必要的 try-catch 块。

你可以在不存储 Car 的情况下存储 Engine 吗?同样的问题适用于所有其他组件。如果必须在创建 Car 的同时创建所有这些组件,则应将这些组件的逻辑全部放在 saveCar 中。如果不是,您的逻辑仍然有点 "obscure",因为您是单独创建事物 — 虽然您可能会与更新操作混淆,更新操作在某些时候可以共享相同的代码。

注意: 我认为传递 Connection 对象不是一个好主意。虽然这没有任何问题,但是当您的程序增长时(如果是这样的话)在某个时候拥有未发布的资源会带来不便。把它看成"a good practice",不是你做不到的,如果它很好understandable/maintainable。

找到这个漂亮的库 DBUtils 解决了我的问题:

private QueryRunner runner = new QueryRunner();   //creating global runner object which used across all methods in my class

public boolean saveCar(Car car){
   Connection con = null;
   try{
        con = ....//get connection
        con.setAutoCommit(false);

        storeCar(car, con);
        storeWheels(car, con);
        storeEngine(car, con);

        DbUtils.commitAndCloseQuietly(con);
   } catch(Exception e){
       DbUtils.rollbackAndCloseQuietly(con);
   } 

}


private void storeWheels(Car car, Connection con) throws Exception{
    String sql = "...";
    runner.update(connection, sql);  //all functionality encapsulated, performing update, closing statement, etc..
}