У меня есть требование в моем приложении Java выполнить набор инструкций БД в атомном & изолированной моде. Например, приложение должно читать строки данных из одной таблицы и обновлять строку данных в другой таблице.Заблокировать набор операций БД в Java
QueryRunner queryRunner = new QueryRunner(); // DBUtils query runner
Object[] params = new Object[] { param };
Connection conn = null;
try {
conn = ...; // get connection
conn.setAutoCommit(false);
result = queryRunner.query(conn, "select x, y, z from table1 where column1 = ?", new BeanHandler<SomeBean>(SomeBean.class), params);
// logic to get value for update
queryRunner.update(conn, "update table2 set p = ? where q = ?", some_value, some_id);
conn.commit();
} catch (SQLException e) {
//
} finally {
DBUtils.closeQuietly(conn);
}
Управление транзакциями достигается путем установки auto commit в false для соединения и в явной фиксации позже, как показано выше. Но приведенный выше код также может быть выполнен в многопоточной среде, и я также хочу, чтобы два оператора БД (выберите & update), которые будут выполняться в целом исключительно взаимно.
У меня есть идея использовать общий объект Java Lock в этом методе, изображенный ниже.
В классе,
private Lock lock = new ReentrantLock(); // member variable
В методе
lock.lock();
try {
conn = ...; // get connection
conn.setAutoCommit(false);
result = queryRunner.query(conn, "select x, y, z from table1 where column1 = ?", new BeanHandler<SomeBean>(SomeBean.class), params);
// logic to get value for update
queryRunner.update(conn, "update table2 set p = ? where q = ?", some_value, some_id);
conn.commit();
} finally {
DBUtils.closeQuietly(conn);
lock.unlock();
}
кажется своего рода способна решить эту проблему. Тем не менее, мне интересно, является ли это лучшей практикой и есть ли для этого лучшая альтернатива (например, рамки)?
Спасибо, Hiro2k. Я считаю, что наше приложение работает в контейнере сервлетов и будет находиться в одной JVM. «SELECT ... FOR UPDATE» может не работать в моем случае, поскольку я обновляю строку в таблице, отличной от таблицы, в которой работает оператор select. – Chen
Правильно, но если вы когда-нибудь решите добавить еще один экземпляр сервера для балансировки нагрузки или масштабирования, тогда вы столкнетесь с этой проблемой. Вы можете добавить 'SELECT ... FOR UPDATE' в строку во второй таблице в самом начале вашего метода, чтобы другим пришлось подождать, пока она не закончится. – Hiro2k
Хорошая точка, @ Hiro2k. Я буду оценивать наши варианты использования на моем конце, чтобы увидеть, можно ли их охватить. – Chen