Hibernate, spring, JPS и изоляция - пользовательская изоляция не поддерживается - PullRequest
23 голосов
/ 08 марта 2011

Я пытался это:

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

на моих методах обслуживания, но весна жалуется, говоря:

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

Как мне решить эту проблему?

Ответы [ 6 ]

10 голосов
/ 12 апреля 2012

Эта реализация не учитывает очистку, я реализовал аналогичное решение, но она также учитывает очистку. Это решение можно найти здесь: http://shahzad -mughal.blogspot.com / 2012/04 / весна-JPA-зимуют-поддержка-на-custom.html

10 голосов
/ 08 марта 2011

JPA не поддерживает пользовательские уровни изоляции.Вы можете расширить класс HibernateJpaDialect и переопределить методы, связанные с подключением, так что вы можете установить пользовательские уровни изоляции для 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 голосов
/ 16 июля 2013

Опираясь на ответ Божо и принимая во внимание комментарии к нему, следующее, по-видимому, является полным (совместимым с Hibernate 4) решением, решающим проблему сброса соединения. Насколько я могу сказать, весенний уровень будет гарантировать вызов метода cleanupTransaction, но если это на самом деле не гарантировано, это может потребовать переосмысления из-за потенциальной утечки памяти permGen и побочных эффектов после запроса на объекте соединения. .

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();
    }
  }
}
0 голосов
/ 25 октября 2013

@ Shahzad Mughal Я оставил вам два пункта ;-) Ваш ответ должен быть принят как правильный.Принятый ответ приведет к тому, что приведенная ниже проблема случайно пропускает ведущих разработчиков, которые считают, что в драйвере mysql есть ошибки, например:

WARN [org.hibernate.util.JDBCExceptionReporter] - Ошибка SQL: 0, SQLState:S1009 ОШИБКА [org.hibernate.util.JDBCExceptionReporter] - Соединение доступно только для чтения.Запросы, ведущие к изменению данных, не разрешены

Подробнее об этом приключении вы можете прочитать в http://thinkinginsoftware.blogspot.com/2013/10/connection-is-read-only-queries-leading.html

0 голосов
/ 20 августа 2013

Вы также можете обернуть bean-компонент «источник данных» с помощью «IsolationLevelDataSourceAdapter», просто выполнив следующее:

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

, где «_dataSource» является ссылкой на фактический источник данных.

0 голосов
/ 08 марта 2011

При указании JpaTransactionManager вы указали JPADialect? По умолчанию я думаю, что он использует DefaultJpaDialect , и вам нужен HibernateJpaDialect .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...