Вам нужна транзакция базы данных для чтения данных?

Когда я пытаюсь прочитать данные из базы данных, по крайней мере, с помощью

((Session)em.getDelegate()).createCriteria()

Исключением являются броски, говорящие о том, что транзакции нет.

Когда я добавляю аннотацию:

@Transactional(
    value = SomeClass.TRANSACTIONAL_MANAGER, 
    propagation = Propagation.SUPPORTS, 
    readOnly = true
)

это работает отлично.

Тем не менее, поскольку чтение будет происходить миллионы раз в секунду для доступа и чтения данных, я хочу убедиться, что наша среда не засорена без необходимости.

Если нет, какова стоимость создания только для чтения Propagation.Supports сделка?

Могу ли я создать Hibernate Criteria Query без транзакции в сочетании с Spring?

2 ответа

Решение

Все операторы базы данных выполняются в контексте физической транзакции, даже если мы явно не объявляем границы транзакции (BEGIN/COMMIT/ROLLBACK).

Если вы не объявляете границы транзакции, то каждый оператор должен быть выполнен в отдельной транзакции (autocommit Режим). Это может даже привести к открытию и закрытию одного соединения на оператор, если ваша среда не может справиться с привязкой соединения на поток.

Объявление услуги как @Transactional даст вам одно соединение на всю длительность транзакции, и все операторы будут использовать это единственное изолированное соединение. Это намного лучше, чем вообще не использовать явные транзакции.

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

JPA не применяет транзакции к операциям чтения. Только записи заканчивают тем, что выдают исключение требуемой транзакции, если вы забыли запустить транзакционный контекст. Тем не менее, всегда лучше объявлять границы транзакций даже для транзакций только для чтения (в Spring@Transactionalпозволяет помечать транзакции только для чтения, что значительно повышает производительность).

Теперь, если вы используете декларативные границы транзакций (например,@Transactional), вам необходимо убедиться, что получение соединения с базой данных задерживается до тех пор, пока не будет выполнен оператор JDBC. В JTA это поведение по умолчанию. При использовании RESOURCE_LOCAL вам необходимо установитьhibernate.connection.provider_disables_autocommit свойство конфигурации и убедитесь, что базовый пул соединений настроен на отключение режима автоматической фиксации.

Согласно моему опыту с реализацией JPA в J2EE, менеджер транзакций всегда необходим для обеспечения безопасности работы CRUD, гарантируя откат для сохранения целостности данных.

Корпоративные приложения используют различные ресурсы для сохранения данных и отправки сообщений, таких как база данных или очередь сообщений. Если мы хотим запросить эти ресурсы последовательно и отменить всю операцию, как только возникнет проблема, мы должны поместить этот запрос в единицу работы, чтобы он выполнялся целиком.

Вы можете определить это:

  • с помощью связанных аннотаций (как показано в вопросах); таким образом, контейнер автоматически загружает менеджер транзакций для заданного контекста постоянства;

  • введя вручную менеджер транзакций, следующим образом:

    public class sample {
    
        @PersistenceContext
        EntityManager em;
    
        // Injected transaction manager
        @Inject
        UserTransaction utx;
    
        private static final String[] GAME_TITLES = {
            "Super Mario Brothers",
            "Mario Kart",
            "F-Zero"
        };
    
        private void clearData() throws Exception {
            utx.begin();
            em.joinTransaction();
            System.out.println("Dumping old records...");
            em.createQuery("delete from Game").executeUpdate();
            utx.commit();
        }
    
        private void insertData() throws Exception {
            utx.begin();
            em.joinTransaction();
            System.out.println("Inserting records...");
            for (String title : GAME_TITLES) {
                Game game = new Game(title);
                em.persist(game);
            }
            utx.commit();
            // clear the persistence context (first-level cache)
            em.clear();
        }
    
        // ...
    
    }
    

Spring Data, как реализация спецификации JPA, может следовать тому же подходу.

Вы можете найти больше информации, прочитав следующую статью: http://en.wikibooks.org/wiki/Java_Persistence/Transactions.

Другие вопросы по тегам