所以我正在写一个REST Api,我为每个资源定义了1个服务类。
因此我有一个Person资源,这就是我与数据库交互的方式。
public class TeacherService {
public static List<Person> getAll() throws SQLException{
//define the query string and objects
try{
DriverManager.registerDriver(new com.mysql.jdbc.Driver ());
connection = (Connection) DriverManager.getConnection(ConnectDb.CONN_STRING, ConnectDb.USERNAME, ConnectDb.PASSWORD);
statement = (PreparedStatement) connection.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
resultSet = statement.executeQuery(query);
//process results
}catch (SQLException e) {
System.err.println(e);
}finally{
//close all shit
}
return list;
}
public static Person getById(int id) throws SQLException{
//repeat
}
public static void addPerson(Person person) throws SQLException {
//repeat
}
public static void upateTeacher(Person person) throws SQLException {
//repeat
}
public static void deleteTeacher(int id) throws SQLException {
//repeat
}
}
所以除了在每种情况下都不同的Query和resultSet处理逻辑之外,每个东西都差不多。 这不仅违反了DRY的许多层面,而且维护起来也非常笨拙。有没有更好的方法来做到这一点。
答案 0 :(得分:1)
这是一个如何实现它的例子。这个例子并不完美,但应该让你走上正确的道路。
基本上,您在打开公共共享连接后注册所有语句。完成所有工作,然后调用shutdown()方法将其全部关闭。
public class MyDataAccessObject {
private final String getAllPersonsQuery = "SELECT persons FROM personTable";
private PreparedStatement psGetAllPersonsQuery;
private final String addPersonQuery = "INSERT INTO personTable (personName) VALUES (?)"; // ? is a placeholder. Using PreparedStatement and ?'s, adds more safety and performance.
private PreparedStatement psAddPersonQuery;
private Connection conn;
private final String connectionString;
private final String username;
private final String password;
public MyDataAccessObject(String connectionString, String username, String password) {
this.connectionString = connectionString;
this.username = username;
this.password = password;
}
public void init() throws SQLException {
conn = DriverManager.getConnection(connectionString, username, password); // no longer required to register driver if using modern JDBC drivers.
psGetAllPersonsQuery = conn.prepareStatement(getAllPersonsQuery);
psAddPersonQuery = conn.prepareStatement(addPersonQuery); // we register these now, so it's fast to use later.
}
public void shutdown() throws SQLException {
if (conn != null) {
conn.close(); // this will close everything used ontop of this connection, including PreparedStatement's, and ResultSets, if still open.
}
}
public List<Person> getAllPersons() throws SQLException {
if (conn == null) {
// try to re-open connection
init();
}
ResultSet rs = psGetAllPersonsQuery.execute();
List<Person> list = new ArrayList<Person>();
while (rs.next()) {
list.add(new Person(rs.getString(1))); // not sure how your data is setup, this is returning the first (1) column from the resultset
}
if (rs != null) {
rs.close();
}
return list;
} // don't close the prepareStatement!
public void addPerson(Person person) throws SQLException {
if (conn == null) {
// try to re-open connection
init();
}
psAddPersonQuery.setString(1, person.getName()); // or however you're storing the data. The 1 is saying replace the first ? with whatever data you specify after the comma.
psAddPersonQuery.executeUpdate(); // executeUpdate() returns an int, which says how many rows were modified. Since you're inserting here, we probably don't care.
} // don't close the prepareStatement!
}
您可以使用它:
MyDataAccessObject mdao = new MyDataAccessObject(connectionString, username, password);
mdao.init(); // now you're ready
List<Person> list = mdao.getAllPersons();
// do stuff with your list
....
mdao.addPerson(someNewPerson);
// ....
// now you're done running, so close it down
mdao.shutdown();