복붙노트

[SPRING] 최대 절전 모드, 봄, JPA 및 격리 - 사용자 정의 격리는 지원되지 않습니다.

SPRING

최대 절전 모드, 봄, JPA 및 격리 - 사용자 정의 격리는 지원되지 않습니다.

나는 이것을 해왔다.

@Transactional(isolation=Isolation.SERIALIZABLE, 
               rollbackFor={Exception.class}, 
               propagation=Propagation.REQUIRES_NEW)

내 서비스 방법에,하지만 봄 말하는 불평 :

Standard JPA does not support custom isolation levels - use a special JpaDialect

이 문제를 어떻게 해결할 수 있습니까?

해결법

  1. ==============================

    1.이 구현은 정리 작업에 대한 설명이 아니며 유사한 솔루션을 구현했지만 정리 작업도 담당합니다. 그 해결책은 여기에서 찾아 낼 수있다 : http://shahzad-mughal.blogspot.com/2012/04/spring-jpa-hibernate-support-for-custom.html

    이 구현은 정리 작업에 대한 설명이 아니며 유사한 솔루션을 구현했지만 정리 작업도 담당합니다. 그 해결책은 여기에서 찾아 낼 수있다 : http://shahzad-mughal.blogspot.com/2012/04/spring-jpa-hibernate-support-for-custom.html

  2. ==============================

    2.JPA는 사용자 정의 격리 수준을 지원하지 않습니다. HibernateJpaDialect 클래스를 확장하고 Connection 관련 메소드를 재정 의하여 Connection에서 사용자 정의 분리 레벨을 설정할 수있다.

    JPA는 사용자 정의 격리 수준을 지원하지 않습니다. HibernateJpaDialect 클래스를 확장하고 Connection 관련 메소드를 재정 의하여 Connection에서 사용자 정의 분리 레벨을 설정할 수있다.

    여기 제가 작성했지만 아직 테스트하지 않은 내용이 있습니다.

    public class HibernateExtendedJpaDialect extends HibernateJpaDialect {
    
        @Override
        public Object beginTransaction(EntityManager entityManager,
                TransactionDefinition definition) throws PersistenceException,
                SQLException, TransactionException {
    
            Session session = (Session) entityManager.getDelegate();
            DataSourceUtils.prepareConnectionForTransaction(session.connection(), definition);
    
            entityManager.getTransaction().begin();
    
            return prepareTransaction(entityManager, definition.isReadOnly(), definition.getName());
        }
    
    }
    

    그리고 이것을 이것을 EntityManagerFactory의 속성으로 정의합니다 :

    <property name="jpaDialect">
        <bean class="com.company.util.HibernateExtendedJpaDialect" />
    </property>
    
  3. ==============================

    3.Bozho의 대답을 읽고 그에 대한 주석을 고려할 때, 다음은 연결을 재설정 할 필요성을 해결하는 완전한 (Hibernate 4 호환) 솔루션 인 것처럼 보입니다. Spring 레이어는 cleanupTransaction 메서드를 호출 할 것이라고 보장 할 수 있지만 실제로 보장되지 않는 경우 연결 개체에 대한 메모리 누수 및 게시 요청 부작용 가능성 때문에 다시 생각해야 할 수도 있습니다 .

    Bozho의 대답을 읽고 그에 대한 주석을 고려할 때, 다음은 연결을 재설정 할 필요성을 해결하는 완전한 (Hibernate 4 호환) 솔루션 인 것처럼 보입니다. Spring 레이어는 cleanupTransaction 메서드를 호출 할 것이라고 보장 할 수 있지만 실제로 보장되지 않는 경우 연결 개체에 대한 메모리 누수 및 게시 요청 부작용 가능성 때문에 다시 생각해야 할 수도 있습니다 .

    public class HibernateExtendedJpaDialect extends HibernateJpaDialect {
    
      ThreadLocal<Connection> connectionThreadLocal = new ThreadLocal<>();
      ThreadLocal<Integer> originalIsolation = new ThreadLocal<>();
    
      @Override
      public Object beginTransaction(EntityManager entityManager,
                                     TransactionDefinition definition) 
          throws PersistenceException, SQLException, TransactionException {
    
        boolean readOnly = definition.isReadOnly();
        Connection connection = 
            this.getJdbcConnection(entityManager, readOnly).getConnection();
        connectionThreadLocal.set(connection);
        originalIsolation.set(DataSourceUtils
            .prepareConnectionForTransaction(connection, definition));
    
        entityManager.getTransaction().begin();
    
        return prepareTransaction(entityManager, readOnly, definition.getName());
      }
    
      /*
    
       We just have to trust that spring won't forget to call us. If they forget,
       we get a thread-local/classloader memory leak and messed up isolation 
       levels. The finally blocks on line 805 and 876 of 
       AbstractPlatformTransactionManager (Spring 3.2.3) seem to ensure this, 
       though there is a bit of logic between there and the actual call to this 
       method.
    
       */
      @Override
      public void cleanupTransaction(Object transactionData) {
        try {
          super.cleanupTransaction(transactionData);
          DataSourceUtils.resetConnectionAfterTransaction(
              connectionThreadLocal.get(), originalIsolation.get());
        } finally {
          connectionThreadLocal.remove();
          originalIsolation.remove();
        }
      }
    }
    
  4. ==============================

    4.@ Shahzad Mughal 나는 당신에게 2 점을 남겼습니다 ;-) 당신의 대답은 올바른 것으로 받아 들여 져야합니다. 받아 들여진 응답은 아래의 문제가 무작위로 예를 들어 mysql 드라이버에 버그가 있다고 생각하는 개발자를 놓치게됩니다.

    @ Shahzad Mughal 나는 당신에게 2 점을 남겼습니다 ;-) 당신의 대답은 올바른 것으로 받아 들여 져야합니다. 받아 들여진 응답은 아래의 문제가 무작위로 예를 들어 mysql 드라이버에 버그가 있다고 생각하는 개발자를 놓치게됩니다.

    http://thinkinginsoftware.blogspot.com/2013/10/connection-is-read-only-queries-leading.html에서이 문제로 모험에 대해 자세히 알아볼 수 있습니다.

  5. ==============================

    5.JpaTransactionManager를 지정할 때 JPADialect를 지정 했습니까? 기본적으로 나는 DefaultJpaDialect를 사용하고 HibernateJpaDialect가 필요하다고 생각한다.

    JpaTransactionManager를 지정할 때 JPADialect를 지정 했습니까? 기본적으로 나는 DefaultJpaDialect를 사용하고 HibernateJpaDialect가 필요하다고 생각한다.

  6. ==============================

    6.다음과 같이 "데이터 소스"빈을 "IsolationLevelDataSourceAdapter"로 래핑 할 수도 있습니다.

    다음과 같이 "데이터 소스"빈을 "IsolationLevelDataSourceAdapter"로 래핑 할 수도 있습니다.

    <bean id="dataSource" class="org.springframework.jdbc.datasource.IsolationLevelDataSourceAdapter">
        <property name="isolationLevelName" value="ISOLATION_READ_COMMITTED"/>
        <property name="targetDataSource" ref="_dataSource"/>
    </bean>
    

    여기서 "_dataSource"는 실제 데이터 소스에 대한 참조입니다.

  7. from https://stackoverflow.com/questions/5234240/hibernate-spring-jps-isolation-custom-isolation-not-supported by cc-by-sa and MIT license