원자 적으로 DB 문 집합을 실행하려면 Java 응용 프로그램에 별도의 요구 사항이 있습니다 (&). 예를 들어, 응용 프로그램은 한 테이블에서 데이터 행을 읽고 다른 테이블의 데이터 행을 업데이트해야합니다.Java에서 DB 작업 집합을 잠급니다.
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);
}
위와 같이 트랜잭션에 대한 자동 커밋을 false로 설정하고 나중에 명시 적으로 커밋하면 트랜잭션 관리가 가능합니다. 그러나 위의 코드는 다중 스레드 환경에서도 실행될 수 있으며 두 개의 DB 문 (& 선택)을 상호 상호 배타적으로 실행하기를 원합니다.
아래에 설명 된 방법에서 공유 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 문이 작동중인 테이블이 아닌 다른 테이블의 행을 업데이트 할 때'SELECT ... FOR UPDATE'가 내 케이스에서 작동하지 않을 수 있습니다. – Chen
그렇지만 부하 분산 또는 확장을 위해 서버의 다른 인스턴스를 추가하기로 결정한 경우이 문제가 발생합니다. 메소드의 맨 처음에 두 번째 테이블의 행에'SELECT ... FOR UPDATE'를 추가하여 다른 사람들이 완료 될 때까지 기다려야합니다. – Hiro2k
좋은 지적, @ Hiro2k. 모든 것을 다룰 수 있는지 알아보기 위해 사용 사례를 평가할 것입니다. – Chen