在JDBC中编写SQL查询的最佳实践是什么?

时间:2013-12-31 19:45:39

标签: java sql servlets jdbc

我正在通过使用JSP和使用JDBC的Servlet开发电子商务Web应用程序来学习Java Web Development。我正在检查GitHub,GoogleCode等中的一些项目,我遇到了一些代码,我发现这些代码在下面的界面中声明了选择,更新,插入方法:

public interface DBDriver {

public void init( DBConnection connection );
public ResultSet selectQuery( String sqlStatement );
public int updateQuery( String sqlStatement );
public ResultSet select( String table, String[] fields, String where );
public ResultSet select( String table, String[] fields, String where, String[] join, String groupBy[], String having, String orderBy[], int start, int limit );
public int insert( String table, HashMap<String, String> fields );
public int update( String table, HashMap<String, String> fields, String where );
public int update( String table, HashMap<String, String> fields, String where, String orderBy[], int start, int limit );
public int delete( String table, String where );
public int delete( String table, String where, String orderBy[], int start, int limit );
public DBConnection getConnection();

}

在另一个类中实现这些方法,例如:DBDriverSQL。

其中一种实施方法是:

public ResultSet select( String table, String[] fields, String where, String[] join, String groupBy[], String having, String orderBy[], int start, int limit ) {
    StringBuilder sql = new StringBuilder();

    /* Make sure a table is specified */
    if( table == null ) {
        throw new RuntimeException();
    }

    sql.append( "SELECT " );

    /* Empty field list means we'll select all fields */
    if( fields == null || fields.length < 1 ) {
        sql.append( "*" );
    }
    else {
        sql.append( Util.joinArray( fields, "," ) );
    }

    /* Add table and fields list to query */
    sql.append( " FROM " ).append( getFullTableName( table ) );

    /* Any JOINs?*/
    if( join != null && join.length > 0 ) {
        sql.append( " " ).append( Util.joinArray( join, " " ) );
    }

    /* Searching on a WHERE condition? */
    if( where != null && !where.isEmpty() ) {
        sql.append( " WHERE " ).append( where );
    }        

    /* Add GROUP BY clause */
    if( groupBy != null && groupBy.length > 0 ) {
        sql.append( Util.joinArray( groupBy, "," ) );
    }

    if( having != null && !having.isEmpty() ) {
        sql.append( " HAVING " ).append( having );
    }

    if( orderBy != null && orderBy.length > 0 ) {
        sql.append( " ORDER BY " ).append( Util.joinArray( orderBy, "," ) );
    }

    if( limit > 0 ) {
        if( start < 1 ) {
            start = 0;
        }

        sql.append( " LIMIT " ).append( start ).append( "," ).append( limit );
    }

    /* Return the compiled SQL code */
    return selectQuery( sql.toString() );
}

在控制器Servlet中调用这些方法,以便从数据库中提取数据。例如:

String where = "listId = " + listId;
    String[] fields = { "b.*, l.listId, l.price, l.comment, l.listDate, l.active, l.condition, l.currency, u.*" };
    String[] join = { "INNER JOIN bzb.book b ON l.isbn=b.isbn",
                "INNER JOIN bzb.user u ON l.userId=u.userId" };
    ResultSet result = bzb.getDriver().select( "booklisting l", fields, where, join, null, null, null, 0, 1 );

我的问题是,与标准的JDBC程序相比,这种方法是否被认为是一种很好的做法,如:

String sql = "select SetID,SetName,SetPrice,SetQuality from setdetails  where heroID = " + id;

        PreparedStatement ps = conn.prepareStatement(sql);
        ResultSet rs = ps.executeQuery();

        while (rs.next()) {

            lists.add(new Set(rs.getInt("SetID"), rs.getString("SetName"), rs.getString("SetPrice"), rs.getString("SetQuality")));
        }
        return lists;

2 个答案:

答案 0 :(得分:4)

我建议你使用标准的JDBC方式(或者如果SQL足够复杂和/或在项目的许多部分中使用,则将SQL作为存储过程移动到数据库中)。我使用连接编写了几个页面的SQL语句,使用DBDriver方法看起来很难看。我建议保持目标,即通过尝试任何难以阅读的编码,使您的所有代码都易于阅读,这可以避免您输入更多行。一个简单的论点是针对结构不良的代码或丑陋的代码来实现较小的性能提升。

请注意,许多SQL模板的目标是避免为每个SQL查询反复编写锅炉代码(try / catch / finally / handle exception)。您提供的示例不会这样做。它只能帮助你构建sql语句。

我建议你使用try / catch / finally块,你可以按照你创建它们的相反顺序关闭finally块中的connection,preparedStatement和resultSet(在关闭它们之前先检查它们是否为null)。 br />
如果抛出SQLException,请捕获它,将导致问题的记录的主键值(用于记录目的)添加到SQLException,然后重新抛出它。

答案 1 :(得分:2)

使用PreparedStament时,传递原始参数没有意义。我会做一些小修改,以使Preparedstatement合规性更高:

String sql = "select SetID,SetName,SetPrice,SetQuality from setdetails  where heroID = ?";

        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setInt(1,intVal);