Write operations are not allowed in read-only mode
Spring 에서 제공 하 는 Open Session In View 를 사용 하여 Write operations are not allowed in read-only mode(Flushmode.NEVER)오류 해결:
Spring 에서 제공 하 는 Open Session In View 를 사용 하지 않 은 상태 에서 service(or Dao)층 에서 session 을 닫 아야 하기 때문에 lazy loading 이 true 이면 응용 층 에서 관계 집합 을 초기 화 해 야 합 니 다.예 를 들 어 copany.getEmployes(),그렇지 않 으 면 Hibernate 던 지기 session already closed Exception; Open Session In View 는 간단 한 방법 을 제공 하여 lazy loading 문 제 를 잘 해결 했다.
이것 은 두 가지 설정 방식 이 있 습 니 다.OpenSession InView Interceptor 와 OpenSession InView Filter(구체 적 으로 SpringSide 참조)는 기능 이 같 습 니 다.하 나 는 웹.xml 에서 설정 하고 다른 하 나 는 application.xml 에서 설정 할 뿐 입 니 다.
Open Session In View 는 request 에서 session 을 현재 thread 에 연결 하 는 동안 hibenate session 을 open 상태 로 유지 하여 session 을 request 의 전체 기간 동안 사용 할 수 있 도록 합 니 다.예 를 들 어 View 층 에서 PO 도 lazy loading 데이터,예 를 들 어${copany.employes}.View 층 논리 가 완 료 된 후에 야 Filter 의 doFilter 방법 이나 Interceptor 의 post Handle 방법 으로 session 을 자동 으로 닫 습 니 다.
OpenSsionInViewInterceptor 설정
...
...
OpenSessionInViewFilter 설정
...
hibernateFilter
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
singleSession
true
...
hibernateFilter
*.do
...
많은 사람들 이 OpenSession InView 를 사용 하 는 과정 에서 오 류 를 언급 합 니 다.
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations
are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into
FlushMode.AUTO or remove 'readOnly' marker from transaction definition
OpenSsionInViewFilter 의 몇 가지 방법 을 보 세 요.
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,FilterChain filterChain)
throws ServletException, IOException {
SessionFactory sessionFactory = lookupSessionFactory();
logger.debug("Opening Hibernate Session in OpenSessionInViewFilter");
Session session = getSession(sessionFactory);
TransactionSynchronizationManager.bindResource(
sessionFactory, new SessionHolder(session));
try {
filterChain.doFilter(request, response);
}
finally {
TransactionSynchronizationManager.unbindResource(sessionFactory);
logger.debug("Closing Hibernate Session in OpenSessionInViewFilter");
closeSession(session, sessionFactory);
}
}
protected Session getSession(SessionFactory sessionFactory)
throws DataAccessResourceFailureException {
Session session = SessionFactoryUtils.getSession(sessionFactory, true);
session.setFlushMode(FlushMode.NEVER);
return session;
}
protected void closeSession(Session session, SessionFactory sessionFactory)
throws CleanupFailureDataAccessException {
SessionFactoryUtils.closeSessionIfNecessary(session, sessionFactory);
}
OpenSession InViewFilter 가 getSession 에 있 을 때 가 져 온 session 의 flush mode 를 Flushmode.NEVER 로 설정 하 는 것 을 볼 수 있 습 니 다.그리고 이 session Factory 를 TransactionSynchronizationManager 에 연결 하여 request 의 전체 과정 을 같은 session 으로 사용 하고 요청 한 후에 이 session Factory 의 연결 을 제거 합 니 다.마지막 으로 closession IfNecessary 는 이 session 이 transaction 과 연결 되 었 는 지 여부 에 따라 session 을 닫 을 지 여 부 를 결정 합 니 다.이 과정 에서 현재 session 에서 readOnly 가 아 닌 transaction 이 있 는 것 을 발견 하면 Flushmode.AUTO Session 을 가 져 와 쓰기 권한 을 가 집 니 다.
public static void closeSessionIfNecessary(Session session, SessionFactory sessionFactory)
throws CleanupFailureDataAccessException {
if (session == null ||
TransactionSynchronizationManager.hasResource(sessionFactory)) {
return;
}
logger.debug("Closing Hibernate session");
try {
session.close();
}
catch (JDBCException ex) {
// SQLException underneath
throw new CleanupFailureDataAccessException("Could not close Hibernate session", ex.getSQLException());
}
catch (HibernateException ex) {
throw new CleanupFailureDataAccessException("Could not close Hibernate session", ex);
}
}
즉,readOnly 가 아 닌 transaction 이 있 으 면 Flush.NEVER 에서 Flush.AUTO 로 전환 할 수 있 습 니 다.insert,update,delete 작업 권한 이 있 고 transaction 이 없 으 며 다른 사람 이 flush model 을 설정 하지 않 았 다 면 doFilter 의 전체 과정 은 Flush.NEVER 입 니 다.그래서 transaction 보 호 를 받 는 방법 은 쓰기 권한 이 있 고 보 호 를 받 지 않 는 방법 은 없습니다.
spring 의 사무 성명 을 사용 하여 방법 을 transaction 에 의 해 제어 합 니 다.
PROPAGATION_REQUIRED,readOnly
PROPAGATION_REQUIRED,readOnly
PROPAGATION_REQUIRED,readOnly
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
상례 에 대해 서 는 save,add,update,remove 로 시작 하 는 방법 으로 쓸 수 있 는 사 무 를 가지 고 있 습 니 다.현재 importExcel()이 라 고 명명 되 어 있 으 면 transaction 이 없어 서 쓸 수 있 는 권한 이 없습니다.이 때 방법 에 insert,update,delete 작업 이 있 으 면 flush model 을 flush.AUTO 로 수 동 으로 설정 해 야 합 니 다.
session.setFlushMode(FlushMode.AUTO);
session.save(user);
session.flush();
오픈 세 션 인 뷰 는 괜찮아 보이 지만 부작용 이 적지 않다.위 에서 OpenSession InViewFilter 의 doFilter Internal 방법 코드 를 보십시오.이 방법 은 실제 적 으로 부모 클래스 의 doFilter 에 의 해 호출 되 었 기 때문에 우 리 는 대략 알 수 있 는 OpenSession InViewFilter 호출 절차:request(요청)->open session 을 시작 하고 transaction->controller->View(JSp)->transaction 을 끝내 고 close session 을 시작 합 니 다.
모든 것 이 정확 해 보 입 니 다.특히 로 컬 개발 테스트 에 문제 가 없 었 지만 절차 중 어느 단계 가 막 히 면 그 동안 connection 은 계속 점용 되 어 풀 리 지 않 았 습 니 다.가장 막 힐 수 있 는 것 은 Jsp 라 는 단 계 를 쓰 는 것 입 니 다.한편 으로 는 페이지 의 내용 이 크 고 response.write 의 시간 이 길 며 다른 한편 으로 는 네트워크 속도 가 느 리 고 서버 와 사용자 간 의 전송 시간 이 길 수 있 습 니 다.대량의 이런 상황 이 발생 하면 연결 탱크 의 연결 이 부족 하여 페이지 의 가사 현상 을 초래한다.
오픈 세 션 인 뷰 는 양 날 의 칼 이 니,공중 망 에 올 려 놓 으 면 콘 텐 츠 가 많 고 트 래 픽 이 많은 사 이 트 는 조심해 야 한다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[JPA] 즉시로딩(EAGER)과 지연로딩(LAZY) (왜 LAZY 로딩을 써야할까?) (1)Proxy는 이 글의 주제인 즉시로딩과 지연로딩을 구현하는데 중요한 개념인데, 일단 원리는 미뤄두고 즉시로딩과 지연로딩이 무엇인지에 대해 먼저 알아보자. 눈 여겨 볼 곳은 'fetch = FetchType.EAGER...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.