Самый чистый способ создать строку SQL в Java

Предупреждение: недопустимое смещение строки 'XXX'

Это происходит, когда вы пытаетесь получить доступ к элементу массива с синтаксисом с квадратной скобкой, но вы делаете это по строке, а не по массиву, поэтому операция явно не имеет смысла .

Пример:

$var = "test";
echo $var["a_key"];

Если вы считаете, что переменная должна быть массивом, см., где она появляется и исправить там проблему.

98
задан Kiquenet 7 June 2017 в 14:37
поделиться

10 ответов

В первую очередь, рассмотрите использование параметров запроса в подготовленных операторах:

PreparedStatement stm = c.prepareStatement("UPDATE user_table SET name=? WHERE id=?");
stm.setString(1, "the name");
stm.setInt(2, 345);
stm.executeUpdate();

другая вещь, которая может быть сделана, состоит в том, чтобы сохранить все запросы в файле свойств. Например, в queries.properties файле может поместить вышеупомянутый запрос:

update_query=UPDATE user_table SET name=? WHERE id=?

Тогда с помощью простого служебного класса:

public class Queries {

    private static final String propFileName = "queries.properties";
    private static Properties props;

    public static Properties getQueries() throws SQLException {
        InputStream is = 
            Queries.class.getResourceAsStream("/" + propFileName);
        if (is == null){
            throw new SQLException("Unable to load property file: " + propFileName);
        }
        //singleton
        if(props == null){
            props = new Properties();
            try {
                props.load(is);
            } catch (IOException e) {
                throw new SQLException("Unable to load property file: " + propFileName + "\n" + e.getMessage());
            }           
        }
        return props;
    }

    public static String getQuery(String query) throws SQLException{
        return getQueries().getProperty(query);
    }

}

Вы могли бы использовать свои запросы следующим образом:

PreparedStatement stm = c.prepareStatement(Queries.getQuery("update_query"));

Это - довольно простое решение, но работает хорошо.

67
ответ дан Piotr Kochański 24 November 2019 в 05:15
поделиться

Как Вы получаете конкатенацию строк кроме длинных строк SQL в PreparedStatements (что Вы могли легко обеспечить в текстовом файле и загрузиться как ресурс так или иначе), что Вы повреждаетесь по нескольким строкам?

Вы не создаете строки SQL, непосредственно Вы? Это является самым большим нет - нет в программировании. Используйте PreparedStatements и снабдите данными как параметрами. Это уменьшает шанс Внедрения SQL значительно.

0
ответ дан JeeBee 24 November 2019 в 05:15
поделиться

Если Вы помещаете строки SQL в файл свойств и затем читаете, что в Вас может сохранить строки SQL в файле простого текста.

, Который не решает проблемы типа SQL, но по крайней мере это делает copying& вставка от ЖАБЫ или sqlplus намного легче.

1
ответ дан Rowan 24 November 2019 в 05:15
поделиться

Я второй рекомендациям для использования ORM нравится, в спящем режиме. Однако существуют, конечно, ситуации, где это не работает, таким образом, я воспользуюсь этой возможностью для рекламирования некоторого материала, который я помог записать: SqlBuilder является библиотекой Java для того, чтобы динамично создать sql операторы с помощью стиля "разработчика". это довольно мощно и довольно гибко.

4
ответ дан james 24 November 2019 в 05:15
поделиться

Я работал над приложением сервлета Java, которое должно создать очень динамические SQL-операторы в специальных целях создания отчетов. Основная функция приложения состоит в том, чтобы подать набор именованных параметров Запроса HTTP в предварительно кодированный запрос и генерировать приятно отформатированную таблицу вывода. Я использовал Spring MVC и платформа внедрения зависимости, чтобы сохранить все мои SQL-запросы в XML-файлах и загрузить их в приложение для создания отчетов, наряду с информацией о форматировании таблицы. В конечном счете требования к отчетности стали более сложными, чем возможности существующих платформ отображения параметра, и я должен был записать свое собственное. Это было интересным упражнением в разработке и произвело платформу для параметра, отображающегося намного более устойчивый, чем что-либо еще, что я мог найти.

новые отображения параметра выглядели как таковыми:

select app.name as "App", 
       ${optional(" app.owner as "Owner", "):showOwner}
       sv.name as "Server", sum(act.trans_ct) as "Trans"
  from activity_records act, servers sv, applications app
 where act.server_id = sv.id
   and act.app_id = app.id
   and sv.id = ${integer(0,50):serverId}
   and app.id in ${integerList(50):appId}
 group by app.name, ${optional(" app.owner, "):showOwner} sv.name
 order by app.name, sv.name

красота получающейся платформы состояла в том, что она могла обработать параметры Запроса HTTP непосредственно в запрос с надлежащей проверкой типа и предельной проверкой. Никакие дополнительные отображения не требуются для контроля ввода. В запросе в качестве примера выше, параметр, названный , serverId был бы проверен, чтобы удостовериться, что он мог бросить к целому числу и был в диапазоне 0-50. Параметр appId был бы обработан как массив целых чисел с пределом длины 50. Если поле showOwner будет присутствовать и набор к "истинному", то биты SQL в кавычках будут добавлены к сгенерированному запросу для дополнительных полевых отображений. поле Several больше отображений типа параметра доступно включая дополнительные сегменты SQL с дальнейшими отображениями параметра. Это допускает столь сложный из отображения запроса, как разработчик может придумать. Это даже имеет средства управления в конфигурации отчета, чтобы определить, будет ли данный запрос иметь заключительные отображения через PreparedStatement или просто работал как предварительно созданный запрос.

Для демонстрационных значений Запроса HTTP:

showOwner: true
serverId: 20
appId: 1,2,3,5,7,11,13

Это произвело бы следующий SQL:

select app.name as "App", 
       app.owner as "Owner", 
       sv.name as "Server", sum(act.trans_ct) as "Trans"
  from activity_records act, servers sv, applications app
 where act.server_id = sv.id
   and act.app_id = app.id
   and sv.id = 20
   and app.id in (1,2,3,5,7,11,13)
 group by app.name,  app.owner,  sv.name
 order by app.name, sv.name

я действительно думаю, что Spring или В спящем режиме, или одна из тех платформ должна предложить более устойчивый механизм отображения, который проверяет типы, допускает сложные типы данных как массивы и другие такие функции. Я записал свой механизм только в моих целях, он не вполне читается из широкого проката. Это только работает с запросами Oracle в данный момент, и весь код принадлежит крупной корпорации. Когда-нибудь я могу взять свои идеи и создать новую платформу с открытым исходным кодом, но я надеюсь, что один из существующих крупных игроков примет вызов.

4
ответ дан Natalia 24 November 2019 в 05:15
поделиться

Я склонен использовать Spring, Назвал Параметры JDBC, таким образом, я могу записать стандартную строку как "выбор * от вздора где colX = ':someValue'"; я думаю, что это довольно читаемо.

альтернатива должна была бы предоставить строку в отдельном .sql файле и считать содержание в использовании служебного метода.

, О, также стоящий взглянуть на Пролеску: https://squill.dev.java.net/docs/tutorial.html

5
ответ дан GaryF 24 November 2019 в 05:15
поделиться

Я взглянул бы на Spring JDBC. Я использую его каждый раз, когда я должен выполнить SQLs программно. Пример:

int countOfActorsNamedJoe
    = jdbcTemplate.queryForInt("select count(0) from t_actors where first_name = ?", new Object[]{"Joe"});

Это является действительно большим для любого вида sql выполнения, особенно запрашивая; это поможет Вам отобразить наборы результатов на объекты, не добавляя сложность полного ORM.

9
ответ дан Bent André Solheim 24 November 2019 в 05:15
поделиться

Я задаюсь вопросом, ли Вы после чего-то как Загогулина . Также что-то очень полезное jDBI. Это не поможет Вам с запросами все же.

12
ответ дан dusan 24 November 2019 в 05:15
поделиться

Одна технология, которую необходимо рассмотреть, SQLJ - способ встроить SQL-операторы непосредственно в Java. Как простой пример, у Вас могло бы быть следующее в файле по имени TestQueries.sqlj:

public class TestQueries
{
    public String getUsername(int id)
    {
        String username;
        #sql
        {
            select username into :username
            from users
            where pkey = :id
        };
        return username;
    }
}

существует дополнительный шаг перед компиляцией, который берет Ваши .sqlj файлы и переводит их в чистый Java - короче говоря, это ищет специальные блоки, разграниченные с

#sql
{
    ...
}

, и превращает их в вызовы JDBC. Существует несколько ключевых преимуществ для использования SQLJ:

  • полностью краткие обзоры далеко уровень JDBC - программисты только должны думать о Java и SQL
  • , который переводчик может быть сделан проверить Ваши запросы на синтаксис и т.д. против базы данных во время компиляции
  • способность непосредственно связать переменные Java в запросах с помощью ":" префикс

существует реализации переводчика вокруг для большинства крупных поставщиков базы данных, таким образом, необходимо быть в состоянии найти все, в чем Вы нуждаетесь легко.

14
ответ дан Ashley Mercer 24 November 2019 в 05:15
поделиться

Почему Вы хотите генерировать весь sql вручную? Посмотрите на Вас, ORM нравится, в спящем режиме В зависимости от Вашего проекта, это, вероятно, сделает по крайней мере 95% того, что Вы нуждаетесь, делаете это более чистым способом тогда необработанный SQL, и если необходимо получить последний бит производительности, можно создать SQL-запросы, которые должны быть настроенной рукой.

4
ответ дан Jared 24 November 2019 в 05:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: