어떻게 synchronized
자바 키워드 작품
synchronized
정적 메소드에 키워드를 추가하면 한 번에 하나의 스레드에서만 메소드를 호출 할 수 있습니다.
귀하의 경우 모든 메소드 호출은 다음을 수행합니다.
- 새로운 것을 만들다
SessionFactory
- 새로운 것을 만들다
Session
- 엔티티를 가져옵니다
- 엔티티를 다시 발신자에게 반환
그러나 요구 사항은 다음과 같습니다.
- 동일한 DB 인스턴스에 대한 정보에 액세스하지 못하도록하고 싶습니다.
getObjectById
특정 클래스에 의해 호출 될 때 모든 클래스에 대한 호출 방지
따라서 getObjectById
메서드가 스레드로부터 안전하더라도 구현이 잘못되었습니다.
SessionFactory
모범 사례
는 SessionFactory
스레드 안전이며,이 엔티티 클래스를 구문 분석하고 내부 엔티티 메타 모델 표현을 구축 할 필요가로 만들 수있는 매우 비싼 개체입니다.
따라서 SessionFactory
모든 getObjectById
메소드 호출 에서 on을 작성해서는 안됩니다 .
대신 싱글 톤 인스턴스를 만들어야합니다.
private static final SessionFactory sessionFactory = new Configuration()
.configure()
.buildSessionFactory();
는 Session
항상 닫아야합니다
당신은을 닫지 않은 Session
A의 finally
블록 및 개체를로드 할 때 예외가 발생하는 경우이 데이터베이스 리소스를 누출 할 수 있습니다.
Session.load
메소드 에 따르면 JavaDoc 은 HibernateException
데이터베이스에서 엔티티를 찾을 수없는 경우 a를 던질 수 있습니다.
이 메소드를 사용하여 인스턴스가 존재하는지 판별하지 않아야합니다 ( get()
대신 사용). 존재하지 않는 것이 실제 오류 인 것으로 가정하는 인스턴스를 검색 할 때만 사용하십시오.
따라서 다음 과 같이 finally
블록을 사용하여 를 닫아야합니다 Session
.
public static synchronized Object getObjectById (Class objclass, Long id) {
Session session = null;
try {
session = sessionFactory.openSession();
return session.load(objclass, id);
} finally {
if(session != null) {
session.close();
}
}
}
다중 스레드 액세스 방지
귀하의 경우 하나의 스레드 만 해당 특정 엔티티에 액세스 할 수 있도록하려고했습니다.
그러나 synchronized
키워드는 두 개의 스레드가 getObjectById
동시에 호출하는 것을 방지 합니다. 두 스레드가이 메소드를 차례로 호출해도이 엔티티를 사용하는 스레드가 두 개가됩니다.
따라서 다른 스레드가 수정할 수 없도록 지정된 데이터베이스 개체를 잠 그려면 데이터베이스 잠금을 사용해야합니다.
synchronized
키워드는 하나의 JVM에서 작동합니다. 웹 노드가 여러 개인 경우 여러 JVM에서 멀티 스레드 액세스를 막을 수 없습니다.
당신이해야 할 일은 다음과 같이 변경 사항을 DB에 적용 LockModeType.PESSIMISTIC_READ
하거나LockModeType.PESSIMISTIC_WRITE
사용 하는 동안입니다.
Session session = null;
EntityTransaction tx = null;
try {
session = sessionFactory.openSession();
tx = session.getTransaction();
tx.begin();
Post post = session.find(
Post.class,
id,
LockModeType.LockModeType.PESSIMISTIC_READ
);
post.setTitle("High-Performance Java Perisstence");
tx.commit();
} catch(Exception e) {
LOGGER.error("Post entity could not be changed", e);
if(tx != null) {
tx.rollback();
}
} finally {
if(session != null) {
session.close();
}
}
그래서 이것이 내가 한 일입니다.
- 나는 새로운 것을 만들고
EntityTransaction
새로운 데이터베이스 트랜잭션을 시작했다
Post
관련 데이터베이스 레코드를 잠그면 서 엔티티를 로드했습니다.
Post
엔터티를 변경하고 거래를 커밋했습니다.
Exception
던져 질 경우 거래를 롤백했습니다.
ACID 및 데이터베이스 트랜잭션에 대한 자세한 내용은 이 기사 도 확인하십시오 .