通过跨多个私有方法使用 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..
}
我正在使用 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..
}