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

Многопользовательское приложение, две зависимые таблицы (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
Транзакции в jdbc
    #33540162
Евгений Путилин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где гарантия того что 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
Транзакции в jdbc
    #33540191
Фотография Vector
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторГде гарантия того что 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
Транзакции в jdbc
    #33540541
funikovyuri
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что за СУБД?
...
Рейтинг: 0 / 0
Транзакции в jdbc
    #33540611
GammiBear
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
0. А сервер БД чисто случайно не MySQL 3.x/4.x ???

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

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

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

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


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


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

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

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


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