Я изучаю веб-разработку на Java, разрабатывая веб-приложение для электронной коммерции с использованием JSP и сервлетов с JDBC. Я проверял некоторые проекты в GitHub, GoogleCode и т.д., и я наткнулся на код, который я нашел необычным, например, объявление методов select, update, insert в интерфейсе, как показано ниже:

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() );
}

Эти методы вызываются в сервлетах контроллера для извлечения данных из базы данных. Пример:

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;
3
Sai Upadhyayula 31 Дек 2013 в 23:45

2 ответа

Лучший ответ

Я предлагаю вам использовать стандартный способ JDBC (или переместить SQL в базу данных в качестве хранимой процедуры, если она достаточно сложна и / или используется во многих частях проекта). Я написал операторы SQL с использованием соединений, которые выполнялись на нескольких страницах, и при использовании метода DBDriver это будет выглядеть некрасиво. Я предлагаю оставаться с целью сделать весь ваш код легко читаемым, вместо попытки любого трудного для чтения кода, который может избавить вас от ввода еще нескольких строк. Аналогичный аргумент - плохо структурированный код или некрасивый код для достижения небольшого прироста производительности.

Обратите внимание, что цель многих шаблонов SQL - избежать повторения кода котла снова и снова (попробуйте / поймать / наконец / обработать исключения) для каждого SQL-запроса. В приведенном вами примере этого не происходит. Это только поможет вам создать инструкцию sql.

Я предлагаю вам использовать блок try / catch / finally, в котором вы закрываете соединение, prepareStatement и resultSet в блоке finally в обратном порядке, в котором вы их создаете (сначала проверяя, являются ли они нулевыми, прежде чем закрывать их).

И если выбрасывается SQLException, поймайте его, добавьте значение первичного ключа записи, вызвавшей проблему (для целей ведения журнала), в SQLException и повторно выбросьте его.

4
user2810910 31 Дек 2013 в 20:08

Когда вы используете PreparedStament, нет смысла передавать необработанный параметр. Я бы сделал небольшую модификацию, чтобы сделать его более Preparedstatement совместимым:

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

        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setInt(1,intVal); 
2
kosa 31 Дек 2013 в 19:49