如果preparedStatements可以根据对象的不同而更改,如何正确地优化JDBC代码



所以我有一个小问题。

在我的Java代码中,我有多个PreparedStatements,根据我的教授的说法,这些语句应该在类的构造函数中实现。为此,我基本上做了这样的事情:

private PreparedStatement getWardStatement, getHospitalStayStatement, deletePatientFromHospitalStayStatement, selectPatientFromPatientStatement, selectWardStatement, averageBedNumberStatement;
private static final String SELECT_FROM_WARD = "SELECT * FROM Ward";
private static final String DELETE_FROM_HOSPITAL_STAY_HO_S_WHERE_HO_S_HO_ID = "DELETE FROM HospitalStay hoS WHERE hoS.HoID= ?";
private static final String SELECT_FROM_PATIENT_P_WHERE_P_PA_ID = "SELECT * FROM Patient p WHERE p.PaID = ?";
private static final String SELECT_FROM_WARD_WHERE_WA_ID = "SELECT * FROM Ward  WHERE waID = ?";
private static final String SELECT_WARD_HOS_P_WITH_PAID = "SELECT * FROM HospitalStay hoS, Patient p , Ward w WHERE hoS.patientid = p.PaID AND hos.wardid = w.waid AND hos.patientid = ?";
private static final String AVERAGE_SQL = "SELECT avg(CAST((hoS.discharge - hoS.admission)AS DOUBLE PRECISION)) AS average FROM HospitalStay hoS WHERE hoS.wardid = ? AND hoS.discharge IS NOT NULL";
private static final String FREEBED_SQL = "SELECT (sum(w.numberofbeds) - (SELECT count(*) FROM HospitalStay WHERE discharge IS NULL)) AS freeBeds FROM Ward w";
private Connection conPSQL;
public BasicDBImpl() {
getConnection();
try {
getWardStatement = conPSQL.prepareStatement(SELECT_FROM_WARD_WHERE_WA_ID);
deletePatientFromHospitalStayStatement = conPSQL.prepareStatement(DELETE_FROM_HOSPITAL_STAY_HO_S_WHERE_HO_S_HO_ID);
selectPatientFromPatientStatement = conPSQL.prepareStatement(SELECT_FROM_PATIENT_P_WHERE_P_PA_ID);
selectWardStatement = conPSQL.prepareStatement(SELECT_FROM_WARD);
getHospitalStayStatement = conPSQL.prepareStatement(SELECT_WARD_HOS_P_WITH_PAID);
averageBedNumberStatement = conPSQL.prepareStatement(AVERAGE_SQL);
} catch (SQLException e) {
throw new FetchException(e);
}
}

我的第一个问题基本上是,我是否可以在构造函数的上下文中使用try/catch。我担心的原因是,如果一个声明没有通过,其他声明也不会通过。。。

我的第二个问题是,如果语句可以更改,那么如何将所有preparedStatements放入构造函数中,这取决于某个对象是否为null。

示例:

public int getNotFreeBeds(Ward ward) {
assert ward == null || ward.isPersistent() : "Ward is not persistent";
String countSql = "SELECT COUNT(*) AS count FROM HospitalStay hoS WHERE hoS.Discharge IS NULL";
if (ward != null) {
countSql += " AND hoS.WardID = ?";
}
try (PreparedStatement preparedStatement = conPSQL.prepareStatement(countSql)) {
if (ward != null) {
preparedStatement.setLong(1, ward.getObjectID());
}
ResultSet set = preparedStatement.executeQuery();
set.next();
return set.getInt("count");
} catch (SQLException e) {
throw new FetchException(e);
}
}

教授说我们应该使用if级联创建所有可能的PreparedStatements,但由于对象的原因,我不知道如何在构造函数中创建。

根据我的教授的说法,这应该在类的构造函数中实现。

这太不幸了。

这意味着你的教授不知道他们在说什么。

getConnection();

名为getX的方法通常应该没有副作用。显然,在这里它不是没有副作用的(调用SEF方法并忽略它们返回的内容是一个无操作(。

private Connection conPSQL;

让连接成为这样的字段是很棘手的;连接是资源-它们是持有系统资源"句柄"的对象;一个只能有几个的资源(在DB连接的情况下,大多数DB都被配置为允许20到100个左右的连接(。问题是,只要Connection对象存在,你就将这100个宝贵插槽中的1个作为"人质",而且你不知道java中的对象何时被垃圾收集。实际上可能需要一周-JVM不会尽快主动收集所有垃圾,这不是它的工作方式(在大多数设置中效率很低(。

这就是为什么必须始终保护资源的原因。您可以使用以下规则集来保护它们:

  1. 您总是使用try (Connection con = openConnection()) { code goes here }构造打开它们:这使您可以访问块中的con,并确保无论代码如何退出此块,con都是关闭的。你可以从它返回,你可以让它运行到底,你可以从中break;,也可以从中抛出一个异常,这都无关紧要-或-
  2. 或者,任何具有资源字段的对象本身都必须成为资源对象:添加implements AutoClosable,添加一个关闭这些资源的close()方法,现在任何使用的代码都需要编写try (YourThing thing = new YourThing()) { ... }才能使用它

任何其他选项都是如此糟糕的风格,它几乎是一个彻头彻尾的错误。

显然,这些都没有发生。

我也不同意,但遗憾的是,我别无选择:(.因为如果我们不这样做,我只会让lol 失败

所以你要求Stack Overflow找到一个水晶球,仔细研究它,并试图了解一个不懂基础知识的教授的首选代码风格是什么?

遗憾的是,我们都没有水晶球了。

上述方法(使您自己的对象本身可自动关闭(也为您提供了关闭那些准备好的语句的途径。此外,如果关闭一个连接,通常从中派生的所有内容(如PreparedStatements(本身都是关闭的。

因此,面对这样做的疯狂想法,唯一明智的策略正是这样。

不过,我敢打赌你的教授并不是在找那个。但是他们在寻找什么呢?好问题。

大概你上这门课是因为你想从事编程职业/想写一个很酷的应用程序/想学习一些东西,而不是因为你的父母否认你,或者你失败了就会被枪杀。你可能想更多地关注学习部分,而不是"疯狂教授想要什么"部分。

最新更新