Разработка c помощью Apache Derby -- тройной выигрыш: Разработка баз данных на Java с помощью Apache Derby, Часть 3

Изменение данных

Учимся вносить изменения в базу данных Apache Derby из Java™-программы. В данной статье на основе материала двух предыдущих статей серии демонстрируется, как создавать и удалять таблицы и выполнять вставку, обновление и удаление данных в базе данных Apache Derby через интерфейс Java -приложения. Для этого используются классы JDBC Statement и PreparedStatement, а также пакеты SQL для повышения производительности.

Роберт Бруннер , ученый-исследователь NCSA, старший преподаватель астрономии, Университет штата Иллинойс, г. Урбана-Шампейн

Роберт Дж. Бруннер (Robert J. Brunner) занимается научными исследованиями в Национальном центре по приложениям для суперкомпьютеров и является старшим преподавателем астрономии в университете штата Иллинойс, город Урбана-Шампейн. Автор нескольких книг и множества статей и практических руководств на различные темы.



10.09.2007

Введение

В предыдущей статье данной серии, "Разработка баз данных на Java с помощью Apache Derby, часть 2" (Web-сайт developerWorks, январь 2007 г.), было показано, как использовать Java-объект Statement для выполнения запроса SQL SELECT к базе данных Apache Derby. Согласно проекту, запрос возвращает набор строк, удовлетворяющих определенным условиям. В результате для выполнения запроса мы используем метод executeQuery объекта Statement; этот метод возвращает набор строк как Java-объект ResultSet.

Но многие инструкции SQL, например, команды языка описания данных (Data Definition Language, DDL), не возвращают наборы строк. Вместо этого они выполняют определенное действие, например, создание таблицы, вставку, обновление или удаление строк. Такие операции возвращают целое значение, представляющее собой код результата действия, например, количество вставленных или удаленных строк или вероятность ошибки. Для операций SQL DDL в случае успешного завершения операции возвращается число 0, как показано в листинге 1. Дополнительную информацию об использовании инструкций SQL DDL с базой данных Apache Derby можно прочитать в третьей статье данной серии.

Листинг 1. Обработка инструкций SQL DDL
..
public class BuildSchema {
...
    private static final String dropProductsSQL = "DROP TABLE bigdog.products" ;

    private static final String createProductsSQL = 
        "CREATE TABLE bigdog.products (" +
            "itemNumber INT NOT NULL," +
            "price DECIMAL(5, 2)," +
            "stockDate DATE," +
            "description VARCHAR(40))" ;

    private static final String productsQuerySQL = 
        "SELECT itemNumber, price, stockDate, description FROM bigdog.products" ;	
 
    static int processStatement(String sql) throws SQLException {
		
        Statement stmt = con.createStatement() ;
        int count = stmt.executeUpdate(sql) ;

        stmt.close() ;
		
        return(count) ;
    }
...
    public static void main(String[] args) {

        try {
            Class.forName(driver) ;
            con = DriverManager.getConnection(url);
...
            processStatement(dropProductsSQL) ;
            processStatement(createProductsSQL) ;

            doProductsQuery(productsQuerySQL) ;

        } catch (SQLException se) {
            printSQLException(se) ;
        }
...

Как и остальные фрагменты Java-кода, представленные в данной статье, этот пример построен на базе примера ThirdQuery из предыдущей статьи. Поэтому здесь показаны только фрагменты листинга кода. (Весь код представлен в сжатом файле в разделе Загрузка.) В этом примере мы сначала определяем несколько Java-объектов String , содержащих код SQL для удаления и создания таблицы bigdog.products, которая используется во всех статьях серии. Затем определяем новый метод, processStatement, который обрабатывает любую подходящую инструкцию SQL, полученную при помощи метода executeUpdate объекта Statement .

Этот метод можно использовать только с теми операциями SQL, которые не возвращают данные, например, команды SQL DDL или операции SQL INSERT, UPDATE или DELETE. Метод передает инструкцию SQL в базу данных Apache Derby, где она обрабатывается, после чего возвращается целочисленное значение. Для операций SQL DDL возвращаемое число равно 0, поэтому в методе main нашего вводного примера его можно проигнорировать. На практике, при работе с более сложными схемами необходимо проверить корректность этого значения.

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

Листинг 2. Изменение схемы базы данных из Java
rb$ mkdir derbyWork
rb$ cd derbyWork
rb$ unzip ../derby11.zip 
Archive:  ../derby11.zip
  inflating: BuildSchema.java        
  inflating: derby.build.sql         
  inflating: FirstInsert.java        
  inflating: FirstUpdate.java        
  inflating: SecondInsert.java       
  inflating: ThirdInsert.java        
rb$ java org.apache.derby.tools.ij < derby.build.sql             
ij version 10.2
...
ij> 
rb$ javac *.java
rb$ java BuildSchema 

ITEMNUMBER |PRICE   |STOCKDATE |DESCRIPTION                             
------------------------------------------------------------------------

0 rows selected

Модернизация базы данных Apache Derby

Вы могли обратить внимание на то, что версия базы данных Apache, указанная в листинге 2 - 10.2. При появлении новой версии базы данных администратору следует быть внимательным. Любые обновления необходимо проводить с осторожностью, следуя хорошо продуманному плану миграции с обязательным проведением регрессивного тестирования в объеме, достаточном для подтверждения нормальной работы критически важных бизнес- приложений. Однако для целей нашей статьи мы можем забыть об осторожности. Новая версия базы данных предлагает несколько дополнительных функций; кроме того, в ней исправлены некоторые программные ошибки, что делает обновление не таким сложным.

Эти шаги довольно просты:

  1. Создайте пустой рабочий каталог, а затем распакуйте код примера в этот каталог;
  2. С помощью инструмента ij Apache Derby запустите прилагаемый файл сценария Apache Derby;
  3. Скомпилируйте все фрагменты Java-кода из этой статьи, а затем выполните Java-программу BuildSchema.

Как видно по выводу нашего примера, класс BuildSchema сначала удаляет, а затем снова создает таблицу bigdog.products, в результате перед нами - новая таблица, в которую можно вставлять данные.

Если при использовании инструмента ij в процессе компиляции или выполнения любого из Java-классов возникла ошибка, то с наибольшей вероятностью причина кроется в переменной окружения Java CLASSPATH. Убедитесь, что эта переменная содержит необходимые JAR-файлы Apache Derby; это можно сделать путем вывода на экран значения этой переменной с помощью команды echo $CLASSPATH; вывод команды будет примерно следующим (учтите, что в вашей установке Apache Derby эти значения могут несколько отличаться): /opt/Apache/db-derby-10.2.1.6-bin/lib/derby.jar:/opt/Apache/db-derby-10.2.1.6-bin/lib/derbytools.jar:..


Инструкции SQL для изменения данных

В предыдущем примере схема bigdog была изменена при помощи таких инструкций SQL DDL, как CREATE и DROP. Этот же процесс можно использовать для вставки новых строк с помощью инструкции SQL INSERT, как показано в листинге 3.

Листинг 3. Обработка инструкций SQL INSERT
...
public class FirstInsert {
...
    private static final String insertProductsSQL = 
        "INSERT INTO bigdog.products(itemNumber, price, stockDate, description) VALUES" ;

    private static final String[] productsData = 
        {"(1, 19.95, '2006-03-31', 'Hooded sweatshirt')",
         "(2, 99.99, '2006-03-29', 'Beach umbrella')",
         "(3, 0.99, '2006-02-28', '')",
         "(4, 29.95, '2006-02-10', 'Male bathing suit, blue')",
         "(5, 49.95, '2006-02-20', 'Female bathing suit, one piece, aqua')",
         "(6, 9.95, '2006-01-15', 'Child sand toy set')",
         "(7, 24.95, '2005-12-20', 'White beach towel')",
         "(8, 32.95, '2005-12-22', 'Blue-stripe beach towel')",
         "(9, 12.95, '2006-03-12', 'Flip-flop')",
         "(10, 34.95, '2006-01-24', 'Open-toed sandal')"} ;

    private static final String productsQuerySQL = 
        "SELECT itemNumber, price, stockDate, description FROM bigdog.products" ;	
...
    public static void main(String[] args) {
...
            int numRows = 0 ;

            for(String product: productsData){
                numRows += processStatement(insertProductsSQL + product) ;
            }

            System.out.println("\n" + numRows + 
                " строки, вставленные в таблицу bigdog.products.") ;

            doProductsQuery(productsQuerySQL) ;
...

Явные запросы: лучший метод

В инструкции SQL INSERT из листинга 3 имена столбцов заданы явным перечислением (itemNumber, price и так далее). Хотя можно опустить этот шаг, поступать так не рекомендуется: это делает код незащищенным от непредвиденных и потенциально незаметных ошибок в том случае, если кто-либо неожиданно внесет изменения в схему, например, переименовав, добавив или удалив столбцы. Явно перечислив имена столбцов и указав их порядок, можно снизить риск возникновения таких ошибок.

В следующей Java-программе FirstInsert мы заменили инструкции SQL DDL инструкцией SQL INSERT, в которую также внесли изменения, чтобы она содержала данные о продукции, добавив два Java-объекта String до вызова метода processStatement. В этом случае вставка каждой строки данных выполняется отдельно, а количество строк, возвращаемых методом processStatement суммируется, чтобы можно было определить, сколько всего строк было вставлено в базу данных.

При помощи этой операции мы вставляем в таблицу bigdog.products те же 10 строк, что и в предыдущих статьях этой серии, но в этом случае вставка осуществляется по одной строке. Вместо этого можно было бы написать один большой объект string и попытаться вставить все данные за один раз -- в нашем случае все 10 строк. Однако это не очень хорошая идея по двум причинам:

  • Выполняя вставку по одной строке, мы получаем более детальный контроль над данными в базе данных. Если при вставке одной из строк произошла ошибка, будет гораздо проще отследить ее источник в том случае, если обрабатывается только одна строка;
  • Использование одного большого объекта Java String для вставки большого количества строк приводит к тяжеловесности кода и усложнению его обслуживания. Учтите, что одновременное добавление нескольких объектов Java String таким способом не рекомендуется; вместо этого следует использовать StringBuffer. Однако в рамках этой статьи для наглядности можно использовать такой упрощенный подход.

Для выполнения этого Java-кода запустите программу FirstInsert. При этом наша таблица bigdog.products пополнится 10 новыми строками, перечисленными в листинге 4.

Листинг 4. Использование Java-кода для вставки данных
rb$ java FirstInsert 

10 rows inserted into bigdog.products table.

ITEMNUMBER |PRICE   |STOCKDATE |DESCRIPTION                             
------------------------------------------------------------------------
1          |19.95   |2006-03-31|Hooded sweatshirt                       
2          |99.99   |2006-03-29|Beach umbrella                          
3          |0.99    |2006-02-28|                                        
4          |29.95   |2006-02-10|Male bathing suit, blue                 
5          |49.95   |2006-02-20|Female bathing suit, one piece, aqua    
6          |9.95    |2006-01-15|Child sand toy set                      
7          |24.95   |2005-12-20|White beach towel                       
8          |32.95   |2005-12-22|Blue-stripe beach towel                 
9          |12.95   |2006-03-12|Flip-flop                               
10         |34.95   |2006-01-24|Open-toed sandal                        

10 rows selected

Подготовленные инструкции SQL

В предыдущем разделе мы вставили 10 строк данных в базу данных Apache Derby, создав Java-объект String, содержащий соответствующие инструкции SQL INSERT. Этот подход функционален, но не оптимален, поскольку требует создания новой статичной инструкции INSERT при каждом вызове метода executeUpdate Java-объекта Statement.

Более эффективно сначала передать базе данных базовую инструкцию INSERT, а затем по мере необходимости передавать релевантные данные отдельно для каждой новой строки. Этот способ позволит базе данных подготовить инструкцию SQL таким же образом, каким компилятор Java обрабатывает Java-функции. Следуя этой аналогии, мы можем затем передать новые параметры этой подготовленной инструкции SQL на обработку Поскольку такой подход может привести к значительному повышению производительности, спецификация JDBC предоставляет класс PreparedStatement, чтобы можно было выполнять операции SQL несколько раз с различными параметрами.

Динамические инструкции SQL INSERT

Из-за разных возможностей этих двух вариантов, использование объекта PreparedStatement отличается от использования объекта Statement. Сначала необходимо изменить базовую инструкцию SQL INSERT при помощи символов "знак вопроса" (?), обозначающих место для вставки параметров. Например, выражение VALUES(?, ?, ?, ?) означает, что в окончательном выражении VALUES инструкции SQL INSERT будут указаны четыре входных параметра. Этот измененный объект String передается на вход метода prepareStatement объекта Connection, что позволяет базе данных Apache Derby перекомпилировать код SQL для ускорения обработки.

Далее необходимо указать значения для каждого из входных параметров. Это делается посредством вызова метода setXXX для каждого входного параметра. Два важных замечания по поводу этого типа методов:

  • XXX заменяют на тип данных параметра, который передается базе данных; например, setInt показывает, что передается целое значение, а setDate показывает, что передается объект Date;
  • Данный метод принимает два параметра: Порядковый номер входного параметра и актуальное используемое значение. Благодаря включению порядкового номера, указывающего, какой из входных параметров должен быть задан, отпадает необходимость задавать входные параметры в определенном порядке.

Хотя использование метода PreparedStatement может показаться сложным, на самом деле это не так, что видно из листинга 5.

Листинг 5. Использование подготовленных инструкций для операций SQL INSERT
..
public class SecondInsert {
...
    private static final String insertProductsSQL = 
        "INSERT INTO bigdog.products(itemNumber, price, stockDate, description) " + 
            "VALUES(?, ?, ?, ?)" ;

    private static final int[] itemNumbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} ;

    private static final BigDecimal[] prices = 
        {new BigDecimal(19.95), new BigDecimal(99.99), new BigDecimal(0.99), 
         new BigDecimal(29.95), new BigDecimal(49.95), new BigDecimal(9.95), 
         new BigDecimal(24.95), new BigDecimal(32.95), 
         new BigDecimal(12.95), new BigDecimal(34.95)} ;

    private static final Date[] dates = 
        {Date.valueOf("2006-03-31"), Date.valueOf("2006-03-29"), 
         Date.valueOf("2006-02-28"), Date.valueOf("2006-02-10"), 
         Date.valueOf("2006-02-20"), Date.valueOf("2006-01-15"),
         Date.valueOf("2005-12-20"), Date.valueOf("2005-12-22"), 
         Date.valueOf("2006-03-12"), Date.valueOf("2006-01-24")} ;

    private static final String[] descriptions = 
        {"Hooded sweatshirt", "Beach umbrella", "", "Male bathing suit, blue", 
         "Female bathing suit, one piece, aqua", "Child sand toy set", 
         "White beach towel", "Blue-stripe beach towel", "Flip-flop", 
         "Open-toed sandal"} ;

    private static final String productsQuerySQL = 
        "SELECT itemNumber, price, stockDate, description FROM bigdog.products" ;	
...
    static void insertData(String sql) throws SQLException {

        int numRows = 0 ;

        PreparedStatement stmt = con.prepareStatement(sql) ;

        for(int itemNumber: itemNumbers){
            stmt.setInt(1, itemNumbers[itemNumber - 1]) ;
            stmt.setBigDecimal(2, prices[itemNumber - 1]) ;
            stmt.setDate(3, dates[itemNumber - 1]) ;
            stmt.setString(4, descriptions[itemNumber - 1]) ;

            numRows += stmt.executeUpdate() ;
        }

        System.out.println("\n" + numRows + 
            " rows inserted into bigdog.products table.") ;

        stmt.close() ;
    }

    public static void main(String[] args) {
...
            insertData(insertProductsSQL) ;
            doProductsQuery(productsQuerySQL) ;
...

Этот пример кода начинается с определения Java-массива, содержащего данные для вставки. В демонстрационном примере такой подход оправдан, но в производственной среде более вероятно, что данные будут считываться из файла или извлекаться из результата вычислений или пользовательского ввода. Остальные изменения, в основном, связаны с изменением кода для использования вместо объекта Statement объекта PreparedStatement. Это такие изменения, как:

  • Создание объекта PreparedStatement;
  • Задание соответствующих входных параметров, в том числе, int, BigDecimal, Date и String;
  • Выполнение инструкции INSERT при помощи метода executeUpdate.

Чтобы понаблюдать за этим принципом в действии, сначала очистите существующую таблицу bigdog.products (это можно cделать, запустив программу BuildSchema), а затем выполните программу SecondInsert, как показано в листинге 6 (в данном листинге для экономии места вывод представлен в сокращенном виде).

Листинг 6. Выполнение подготовленной инструкции Java INSERT statements
rb$ java BuildSchema

ITEMNUMBER |PRICE   |STOCKDATE |DESCRIPTION                             
------------------------------------------------------------------------

0 rows selected
rb$ java SecondInsert

10 rows inserted into bigdog.products table.

ITEMNUMBER |PRICE   |STOCKDATE |DESCRIPTION                             
------------------------------------------------------------------------
1          |19.94   |2006-03-31|Hooded sweatshirt                       
...     
10         |34.95   |2006-01-24|Open-toed sandal                        

10 rows selected

Динамические обновления и выборки

Как и объект Statement, объект PreparedStatement можно использовать не только для операций SQL INSERT, но и для других операций SQL. Например, можно выборочно изменять ( UPDATE), удалять ( DELETE), и даже выбирать (SELECT) данные из базы данных Apache Derby при помощи соответствующим образом настроенного объекта PreparedStatement. В листинге 7 используется объект PreparedStatement для обновления строк в таблице bigdog.products , а затем осуществляется выборка этих строк с помощью еще одного объекта PreparedStatement.

Listing 7. Использование подготовленных инструкций для операций SQL UPDATE и DELETE
...
public class FirstUpdate {
...
    private static final String updateProductsSQL = 
        "UPDATE bigdog.products SET price = price * 1.25, " + "" +
            "stockDate = CURRENT_DATE WHERE price > ?" ; 

    private static final String productsQuerySQL = 
        "SELECT itemNumber, price, stockDate, description " + 
            "FROM bigdog.products WHERE price > ?" ;	
...
    static void doProductsQuery(String sql) throws SQLException {
...
        PreparedStatement stmt = con.prepareStatement(sql) ;
        BigDecimal threshold = new BigDecimal(40.00) ;

        stmt.setBigDecimal(1, threshold) ;		

        ResultSet rs = stmt.executeQuery() ;
...
    }

    static void updateData(String sql) throws SQLException {

        PreparedStatement stmt = con.prepareStatement(sql) ;
        BigDecimal threshold = new BigDecimal(40.00) ;

        stmt.setBigDecimal(1, threshold) ;		

        int numRows = stmt.executeUpdate() ;

        System.out.println("\n" + numRows + " rows updated in bigdog.products table.") ;

        stmt.close() ;
    }

    public static void main(String[] args) {
...
            doProductsQuery(productsQuerySQL) ;						
            updateData(updateProductsSQL) ;
            doProductsQuery(productsQuerySQL) ;
...

В классе FirstUpdate мы сначала определяем две инструкции SQL, которые будут переданы для создания двух объектов PreparedStatement. Первая инструкция - SQL UPDATE , обновляющая цены во всех строках, в которых уже имеется цена, превышающая заданное пороговое значение. Вторая инструкция SQL SELECT предназначена для выборки всех строк, в которых значение цены превышает некоторое пороговое значение. Мы определяем новые методы, чтобы выполнить эти две операции по отдельности, а затем выполняем запрос, изменяем данные и снова выполняем тот же запрос, чтобы проверить результаты операции SQL UPDATE. Результаты выполнения описанной Java-программы показаны в листинге 8.

Листинг 8. Выполнение подготовленных инструкций UPDATE и SELECT
rb$ java FirstUpdate

ITEMNUMBER |PRICE   |STOCKDATE |DESCRIPTION                             
------------------------------------------------------------------------
2          |99.98   |2006-03-29|Beach umbrella                          
5          |49.95   |2006-02-20|Female bathing suit, one piece, aqua    

2 rows selected

2 rows updated in bigdog.products table.

ITEMNUMBER |PRICE   |STOCKDATE |DESCRIPTION                             
------------------------------------------------------------------------
2          |124.97  |2006-11-03|Beach umbrella                          
5          |62.43   |2006-11-03|Female bathing suit, one piece, aqua    

2 rows selected

Пакеты операций

Использование PreparedStatement повышает характеристики гибкости и производительности Java-кода, но код все же не является оптимальным. Причина в том, что каждая операция SQL INSERT (или другая операция SQL) выполняется в рамках отдельной транзакции. Как мы узнали из второй статьи данной серии, транзакция - это логическая единица работы, которую Apache Derby использует для того, чтобы обеспечить целостность базы данных. В пределах одной транзакции все операции либо успешно завершаются, либо действия всех операций отменяются, или, говоря более формальным языком, откатываются до предшествовавшего транзакции состояния базы данных.

Согласно проекту, при каждом вызове метода executeUpdate (или метода executeQuery), операция считается отдельной транзакцией. Это приводит к снижению производительности из-за расходов ресурсов на определение и завершение нескольких транзакций. Более правильно было бы передать пакет инструкций SQL базе данных и выполнить их все вместе. Спецификация JDBC поддерживает функцию пакетной обработки в целях повышения производительности, как показано в листинге 9.

Листинг 9. Использование пакета инструкций SQL INSERT
...
public class ThirdInsert {
...
 private static final String insertProductsSQL = 
   "INSERT INTO bigdog.products(itemNumber, price, stockDate, description) " + 
       "VALUES(?, ?, ?, ?)" ;
...
 static void batchInsertData(String sql) throws SQLException {

   PreparedStatement stmt = con.prepareStatement(sql) ;

   for(int itemNumber: itemNumbers){
       stmt.setInt(1, itemNumbers[itemNumber - 1]) ;
       stmt.setBigDecimal(2, prices[itemNumber - 1]) ;
       stmt.setDate(3, dates[itemNumber - 1]) ;
       stmt.setString(4, descriptions[itemNumber - 1]) ;
       stmt.addBatch() ;
   }

   int numRows = 0 ;	
   int[] counts = stmt.executeBatch() ;

   for(int count: counts){
       numRows += count ;
   }
        
   System.out.println("\n" + numRows + 
       " rows inserted into bigdog.products table.") ;

   stmt.close() ;
 }

 public static void main(String[] args) {
...
       con.setAutoCommit(false) ;
            
       batchInsertData(insertProductsSQL) ;
       doProductsQuery(productsQuerySQL) ;
            
       con.commit() ;
            
   }catch(BatchUpdateException bue) {
       try{
          con.rollback() ;
        		
          System.err.println("Batch Update Exception: Transaction Rolled Back") ;
          printSQLException((SQLException)bue) ;
       }catch(SQLException se){
          printSQLException(se) ;
        	}
...

Главное изменение в классе ThirdInsert по сравнению с предыдущими двумя примерами кода SQL INSERT - это новый метод batchInsertData, использующий метод addBatch для добавления каждого полностью определенного PreparedStatement в пакет инструкций. Эти инструкции выполняются все вместе в пределах одной транзакции посредством вызова метода executeBatch. Для большого количества инструкций SQL этот подход оказывается намного более быстрым, поскольку базе данных Apache Derby приходится определять только одну транзакцию для каждого пакета инструкций.

Метод executeBatch возвращает массив целых чисел, причем каждый элемент массива соответствует количеству строк, которые были вставлены, обновлены или удалены соответствующей инструкцией пакета. В данном примере в нашем пакете 10 инструкций, поэтому массив включает 10 целых чисел; итерируя на этом массиве, можно получить общее количество строк, измененных при выполнении пакета. Важное указание: Это ясно показывает, что в пакет SQL можно включить только команды изменения данных SQL, такие как операции CREATE, DROP, INSERT, UPDATE и DELETE. Если вы попытаетесь включить в пакет команду SQL наподобие запроса SELECT, возвращающего любое значение, кроме одного обновления счетчика, то метод executeBatch обработает исключительную ситуацию.

Вызов метода batchInsertData также требует нескольких изменений нашего метода main:

  1. Перед настройкой пакета отключите режим autocommit (автофиксация) для текущего соединения с базой данных. Таким образом вы предотвратите автоматическое применение SQL-операций нашего пакета к базе данных, что вряд ли можно назвать желательным, если мы допустим какую-либо ошибку;
  2. Добавьте операцию явной фиксации (explicit commit) после того, как пакет будет успешно обработан;
  3. Добавьте обработчик исключительных ситуаций для метода BatchUpdateException, который будет вызван, если при обработке пакета в базе данных возникнут проблемы.

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

Чтобы протестировать пример пакета инструкций для вставки строк, сначала удалите все записи в таблице bigdog.products, а затем выполните программу ThirdInsert , как показано в листинге 10.

Листинг 10. Выполнение пакета инструкций для вставки данных
rb$ java BuildSchema

ITEMNUMBER |PRICE   |STOCKDATE |DESCRIPTION                             
------------------------------------------------------------------------

0 rows selected
rb$ java ThirdInsert

10 rows inserted into bigdog.products table.

ITEMNUMBER |PRICE   |STOCKDATE |DESCRIPTION                             
------------------------------------------------------------------------
1          |19.94   |2006-03-31|Hooded sweatshirt                       
...
10         |34.95   |2006-01-24|Open-toed sandal                        

10 rows selected

Заключение

Из этой статьи вы узнали, как использовать Java-программы для изменения содержимого базы данных Apache Derby, в том числе, об использовании объектов Statement для выполнения операций SQL DDL и SQL INSERT. Затем вы научились использовать объекты PreparedStatement для выполнения команд изменения данных SQL, динамически создаваемых в базе данных Apache Derby в процессе выполнения. В завершение было показано, как сконструировать и выполнить пакет команд SQL, чтобы повысить производительность Java- приложений, которым приходится выполнять большой объем команд изменения данных SQL. В следующих статьях на базе этих основных знаний и навыков демонстрируется, как выполнять более сложные операции базы данных в пользовательских Java-приложениях.


Загрузка

ОписаниеИмяРазмер
Derby SQL script and Java code for this articlederby11.zip8 Кб

Ресурсы

Научиться

Получить продукты и технологии

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Open source, Технология Java, Information Management
ArticleID=254366
ArticleTitle=Разработка c помощью Apache Derby -- тройной выигрыш: Разработка баз данных на Java с помощью Apache Derby, Часть 3
publish-date=09102007