用Java设计数据访问类

用Java设计数据访问类,java,Java,因此,我正在编写一个RESTAPI,并为每个资源定义了一个服务类 因此,我有一个人力资源,这就是我与数据库交互的方式 public class TeacherService { public static List<Person> getAll() throws SQLException{ //define the query string and objects try{ DriverManage

因此,我正在编写一个RESTAPI,并为每个资源定义了一个服务类

因此,我有一个人力资源,这就是我与数据库交互的方式

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        
    }


}
公共类教师服务{
公共静态列表getAll()引发SQLException{
//定义查询字符串和对象
试一试{
registerDriver(新的com.mysql.jdbc.Driver());
connection=(connection)DriverManager.getConnection(ConnectDb.CONN_字符串、ConnectDb.USERNAME、ConnectDb.PASSWORD);
语句=(PreparedStatement)连接.prepareStatement(查询,结果集.TYPE\u滚动\u不敏感,
结果集CONCUR_只读);
resultSet=语句.executeQuery(查询);
//过程结果
}捕获(SQLE异常){
系统错误println(e);
}最后{
//闭嘴
}
退货清单;
}
publicstaticpersongetbyid(intid)抛出SQLException{
//重复
}
公共静态void addPerson(Person-Person)引发SQLException{
//重复
}
公共静态void upateTeacher(Person)引发SQLException{
//重复
}
公共静态void deleteeteacher(int-id)引发SQLException{
//重复
}
}
因此,除了在每种情况下都不同的查询和resultSet处理逻辑之外,每件事都几乎是一样的。
这不仅在许多层面上违反了DRY标准,而且维护起来也显得极为笨拙。有没有更好的办法

下面是一个例子,说明你可能会如何做。这个例子并不完美,但应该让你走上正确的道路

基本上,在打开公共共享连接后,您可以注册所有语句。完成所有工作,然后调用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{
私有最终字符串getAllPersonQuery=“从personTable中选择人员”;
私有预处理语句psGetAllPersonQuery;
private final String addPersonQuery=“INSERT INTO personTable(personName)VALUES(?);/?”是一个占位符。使用PreparedStatement和?增加了更多安全性和性能。
私有预处理语句psadPersonQuery;
专用连接连接器;
私有最终字符串连接字符串;
私有最终字符串用户名;
私有最终字符串密码;
公共MyDataAccessObject(字符串连接字符串、字符串用户名、字符串密码){
this.connectionString=connectionString;
this.username=用户名;
this.password=密码;
}
public void init()引发SQLException{
conn=DriverManager.getConnection(connectionString、用户名、密码);//如果使用现代JDBC驱动程序,则不再需要注册驱动程序。
psGetAllPersonQuery=conn.prepareStatement(GetAllPersonQuery);
psAddPersonQuery=conn.prepareStatement(addPersonQuery);//我们现在注册这些,这样以后使用起来很快。
}
public void shutdown()引发SQLException{
如果(conn!=null){
conn.close();//这将关闭此连接上使用的所有内容,包括PreparedStatement和ResultSet(如果仍然打开)。
}
}
公共列表getAllPersons()引发SQLException{
如果(conn==null){
//尝试重新打开连接
init();
}
ResultSet rs=psGetAllPersonQuery.execute();
列表=新的ArrayList();
while(rs.next()){
list.add(newperson(rs.getString(1));//不确定数据是如何设置的,这将从结果集中返回第一(1)列
}
如果(rs!=null){
rs.close();
}
退货清单;
}//不要关闭prepareStatement!
public void addPerson(Person-Person)抛出SQLException{
如果(conn==null){
//尝试重新打开连接
init();
}
psAddPersonQuery.setString(1,person.getName());//或以何种方式存储数据。1的意思是用逗号后指定的任何数据替换第一个。
psAddPersonQuery.executeUpdate();//executeUpdate()返回一个int,表示修改了多少行。由于您在此处插入,我们可能不在乎。
}//不要关闭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();
MyDataAccessObject mdao=新的MyDataAccessObject(connectionString、用户名、密码);
mdao.init();//现在你准备好了
List List=mdao.getAllPersons();
//用你的清单做些事情
....
mdao.addPerson(someNewPerson);
// ....
//现在你跑完了,把它关掉
mdao.shutdown();

我建议不要在每次需要查询时打开新连接-->运行查询-->关闭连接。打开和关闭将产生大量开销,并大大降低速度。相反,在创建新的TeacherService对象时打开连接,并保持连接打开,直到关闭/停止/销毁TeacherService对象。重新使用连接。您可以对PreparedStatements执行相同的操作(即,在打开的连接上准备所有语句,并保留对已创建对象的引用,以便快速重用)。您可以提供一些代码片段吗?因为结果集和语句都不同,我应该关闭哪一个。谢谢,这太棒了。