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 의 시간 이 길 며 다른 한편 으로 는 네트워크 속도 가 느 리 고 서버 와 사용자 간 의 전송 시간 이 길 수 있 습 니 다.대량의 이런 상황 이 발생 하면 연결 탱크 의 연결 이 부족 하여 페이지 의 가사 현상 을 초래한다.
오픈 세 션 인 뷰 는 양 날 의 칼 이 니,공중 망 에 올 려 놓 으 면 콘 텐 츠 가 많 고 트 래 픽 이 많은 사 이 트 는 조심해 야 한다.

좋은 웹페이지 즐겨찾기