Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Транзакции в jdbc / 11 сообщений из 11, страница 1 из 1
13.02.2006, 10:36
    #33540082
Vector
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции в jdbc
Здравствуйте.

Многопользовательское приложение, две зависимые таблицы (master-detail).
HB_Auto - master, HB_AutoTanks - detail.
В таблицах есть специальное поле f_Locked в которое заносится
идентификатор залогинившегося пользователя, который эту запись заблокировал.

Попытка удалить запись в родительской таблице:
Перед удалением записи в родительской таблице, пытаюсь удалить все записи
в дочерней таблице. Перед удалением записи из дочерней таблицы, проверяю
ее на занятость. Если хотя бы одна запись занята, то надо откатить все
изменения. Т.е. вернуть все удаленные записи в дочерней таблице:
Делаю так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
    String id=getCurrentCarID(); //Получаю идентификатор записи в таблице master
     if (id.compareTo("")!= 0 ){ //Проверка на нулевое значение этого идентификатора
        String free=database.checkIfRecordFree("HB_Cars", id); //Проверка на свободность записи в таблице master (реализовано в моем классе database)
         if (free.compareTo("")== 0 ){ //Если запись свободна, то free=="", иначе - идентификатор пользователя, занявшего запись
            javax.swing.table.DefaultTableModel tm=(javax.swing.table.DefaultTableModel)Table.getModel();
            String auto=((Type)tm.getValueAt(Table.getSelectedRow(),  0 )).toString()+tm.getValueAt(Table.getSelectedRow(),  0 ).toString();
             if (javax.swing.JOptionPane.showConfirmDialog( null , "Вы уверены, что хотите удалить автомобиль: ["+auto+"]?", "ВНИМАНИЕ!!!", javax.swing.JOptionPane.YES_NO_OPTION)== 0 ){
                 try  {
                     try  {
                        //Выключаю режим autocommit
                        database.getConnection().setAutoCommit(false);
                        //Пытаюсь удалить записи в detail таблице
                        //Сначала выбираю все подчиненные записи
                        String query="SELECT f_ID FROM HB_AutoTanks WHERE fl_ParID='"+id+"'";
                        java.sql.ResultSet rs=database.getConnection().createStatement().executeQuery(query);
                        String locked;
                        //Перебираем все подчиенные записи, с проверкой на занятость
                         while (rs.next()){
                            locked=database.checkIfRecordFree("HB_AutoTanks", rs.getString("f_ID"));
                             if (locked.compareTo("")== 0 ) { //Если locked=="" -то свободна запись
                                query="DELETE FROM HB_AutoTanks WHERE f_ID='"+rs.getString("f_ID")+"'";
                                //Собственно удаление дочерней записи
                                database.getConnection().createStatement().executeUpdate(query);
                            }  else  { 
                                //Если запись заблокирована, то бросаем исключение
                                 throw   new  java.sql.SQLException("Не могу удалить танки автомобиля. Данные заблокированы пользователем:["+database.getNameLoginedUser(locked)+"]"); }
                            }
                            //Удаляем запись из master таблицы
                            query="DELETE FROM HB_Auto WHERE f_ID='"+id+"'";
                            database.getConnection().createStatement().executeUpdate(query);
                            //Подтверждаем все изменения
                            database.getConnection().commit();
                            //Переключаемся обратно в режим AutoCommit
                            database.getConnection().setAutoCommit(true);
                            updateData();  //Обновляем данные на форме
                        }  catch (java.sql.SQLException sqlex) {
                            //Что-то не так откатываем изменения
                             try  {
                                database.getConnection().rollback();
                                //И обратно в режим autocommit
                                database.getConnection().setAutoCommit(true);
                            }  catch  (java.sql.SQLException sqlex1)    {
                                javax.swing.JOptionPane.showMessageDialog( null , "Не могу откатить изменения:\nошибка:["+sqlex.getMessage()+"],\nSQL состояние:["+sqlex.getSQLState()+"],\nошибка поставщика:["+sqlex1.getErrorCode()+"]", "Error", javax.swing.JOptionPane.ERROR_MESSAGE);
                        }
                            javax.swing.JOptionPane.showMessageDialog( null , "Не могу удалить данные:\nошибка:["+sqlex.getMessage()+"],\nSQL состояние:["+sqlex.getSQLState()+"],\nошибка поставщика:["+sqlex.getErrorCode()+"]", "Error", javax.swing.JOptionPane.ERROR_MESSAGE);
                    }
                }  catch (java.sql.SQLException sqlex) {
                    javax.swing.JOptionPane.showMessageDialog( null , "Не могу удалить данные:\nошибка:["+sqlex.getMessage()+"],\nSQL состояние:["+sqlex.getSQLState()+"],\nошибка поставщика:["+sqlex.getErrorCode()+"]", "Error", javax.swing.JOptionPane.ERROR_MESSAGE);
                } 
            }    
        }  else  {
            javax.swing.JOptionPane.showMessageDialog( null , "Данные заблокированы пользователем: ["+database.getNameLoginedUser(free)+"]", "Information", javax.swing.JOptionPane.INFORMATION_MESSAGE);
        }
    }

Допустим, что 5 строка в дочерней таблице заблокирована. При выполнении
этого кода будут удалены первые 4 строки, перед тем, как будет обнаружена,
что 5 занята, и должен произойти откат удаления первых 4 записей!
А он не происходит. Т.е. в отладчике я проверяю - действительно выполняется
метод .rollback(), но эффекта нет. Удаленные записи уже безвозвратно
потеряны.
Наверное, я не понял документацию. Поясните в чем дело?
С уважением Vector
...
Рейтинг: 0 / 0
13.02.2006, 11:01
    #33540162
Евгений Путилин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции в jdbc
Где гарантия того что database.getConnection() возвращает всегда один и тотже Connection?

Делаеш все немного глупо.
1. Если хочеш удалить то можно использовать создание FK с ON DELETE CASCADE.

2. Выгоднее вначале заблокировать все записи командой
Код: plaintext
 UPDATE HB_Auto WHERE f_ID=f_ID where f_ID=:id 
И уже потом на них выполнять
Код: plaintext
DELETE 
...
Рейтинг: 0 / 0
13.02.2006, 11:10
    #33540191
Vector
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции в jdbc
авторГде гарантия того что database.getConnection() возвращает всегда один и тотже Connection?

В классе database есть указатель на объект Connection, который создается в начале работы программе и не изменяется, т.е. приложение работает только с одим соединением. Во все конструкторы фреймов я передаю этот указатель, поэтому везде работаю только с один подключением к базе данных.

автор1. Если хочеш удалить то можно использовать создание FK с ON DELETE CASCADE.

Я так понимаю FK - это Foreign Key? Все связи между таблицами у меня определены логикой приложения, а не самой базой данных. Сделано это для облегчения переноса базы данных с одной СУДБ на другую.

автор2. Выгоднее вначале заблокировать все записи командой


UPDATE HB_Auto WHERE f_ID=f_ID where f_ID=:id
И уже потом на них выполнять

DELETE

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

Самое оптимальное здесь - это транзакция. Одна транзакция.
Которая не работает. И меня собстенно интересует почему она не работает. Именно это и является вопросом.
...
Рейтинг: 0 / 0
13.02.2006, 12:45
    #33540541
funikovyuri
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции в jdbc
Что за СУБД?
...
Рейтинг: 0 / 0
13.02.2006, 13:03
    #33540611
GammiBear
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции в jdbc
0. А сервер БД чисто случайно не MySQL 3.x/4.x ???

1. если приложение [многопользовательское], то все ли в порядке с синхронизацией доступа к соединению из разных потоков?

2. Неплохо было бы ознакомится с документаций к используемому JDBC драйверу. смысл заключается в том, что JDBC - это набор интерфейсов. Конкретный драйвер может реализовывать НЕ ВСЕ интерфейсы, либо реализовывать их НЕПОЛНОСТЬЮ.
в вашем случае,например, это может означать что setAutoCommit(false) может ничего не делать, а собственно опцию автокоммита надо устанавливать с помощью свойств соединения(см. DriverManager.getConnection(2) ) либо через SQL.
...
Рейтинг: 0 / 0
13.02.2006, 13:03
    #33540614
Vector
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции в jdbc
В данный момент работаю с MySQL 5 через драйвер, который дают разработчики: mysql-connector-java-3.1.12
...
Рейтинг: 0 / 0
13.02.2006, 14:05
    #33540894
Евгений Путилин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции в jdbc
Vector2. Выгоднее вначале заблокировать все записи командой


UPDATE HB_Auto WHERE f_ID=f_ID where f_ID=:id
И уже потом на них выполнять

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

Ты о чем говориш? если у тебя на n-шаге возникнет блокировка выводиш сообщение и по roolback ты все освобождаеш.
VectorСамое оптимальное здесь - это транзакция. Одна транзакция.

Которая не работает. И меня собстенно интересует почему она не работает. Именно это и является вопросом.
Скорее всего ответ вот в этом:
VectorВ данный момент работаю с MySQL 5 через драйвер, который дают разработчики: mysql-connector-java-3.1.12
...
Рейтинг: 0 / 0
13.02.2006, 14:11
    #33540917
Vector
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции в jdbc
Народ! Кажется разобрался!

Дело в том, что у меня не использовался InnoDB Engine Storage, а использовался MyISAM Engine Storage, соответственно транзакции не работали на стороне сервера.
Сейчас все заработало.

Спасибо всем участникам!
Всем удачи!
С уважением Vector
...
Рейтинг: 0 / 0
13.02.2006, 16:47
    #33541457
unicornmirage
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции в jdbc
Vector
Дело в том, что у меня не использовался InnoDB Engine Storage, а использовался MyISAM Engine Storage, соответственно транзакции не работали на стороне сервера.


пожалуйста, поясните, если не трудно, что такое InnoDB Engine Storage и MyISAM Engine Storage , и каким образом это может влиять на транзакции?
...
Рейтинг: 0 / 0
13.02.2006, 17:19
    #33541574
Кувалдин Роман
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции в jdbc
unicornmirage Vector
Дело в том, что у меня не использовался InnoDB Engine Storage, а использовался MyISAM Engine Storage, соответственно транзакции не работали на стороне сервера.


пожалуйста, поясните, если не трудно, что такое InnoDB Engine Storage и MyISAM Engine Storage , и каким образом это может влиять на транзакции?

Это разные типы хранилища данных для MySQL. MyISAM - быстрый на селектах, но не поддерживает кучу возможностей, в том числе и транзакции. InnoDB более медленный на селектах, но более "фичастый".

Подробнее здесь
...
Рейтинг: 0 / 0
13.02.2006, 23:36
    #33542208
unicornmirage
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции в jdbc
спасибо, почитаю!
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Транзакции в jdbc / 11 сообщений из 11, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]