Как работает распространение транзакций при использовании Open Session In View? - PullRequest
6 голосов
/ 31 октября 2009

Меня очень смущает распространение транзакций в Spring с помощью Hibernate. Я использую аннотации Spring @Transactional в моих методах сервисного уровня. Некоторые помечены как «только для чтения = истина». Если один из моих сервисных методов только для чтения вызывает метод, который не доступен только для чтения, как я могу с этим справиться?

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

Учитывая все это, я не понимаю, как работает Open Session In View (OSIV)! Конечно, используя OSIV в Spring, OpenSessionInViewFilter должен запустить транзакцию до вызова сервисных методов. В этом случае он должен определить, доступна ли транзакция только для чтения или для чтения-записи. НО, как это может знать это? Он не знает, что произойдет под прикрытием уровня обслуживания.

Я нахожусь в полном неведении по поводу всего этого и хотел бы, чтобы кто-нибудь объяснил мне это!

Ответы [ 3 ]

6 голосов
/ 03 января 2010

Жизненный цикл сеансов Hibernate отличается от жизненного цикла транзакций. Они могут перекрывать друг друга.

В случае OpenSessionInViewFilter это никак не связано с транзакциями, оно просто управляет жизненным циклом сеанса Hibernate во время запроса. Когда вызывается Spring-транзакционный метод, новая транзакция запускается и связывается с сеансом гибернации, а затем фиксируется / откатывается при выходе из метода. Затем сеанс закрывается фильтром по окончании запроса. Нет необходимости начинать / завершать транзакцию одновременно с сеансом.

Что касается вашего read-only вопроса о транзакции (что, кстати, является совсем другой проблемой), это на самом деле не более чем намек на базовую базу данных, что никакие данные не будут изменены. Я никогда не видел, чтобы это имело какой-либо конкретный эффект, хотя, кажется, он более полезен в качестве инструмента документирования, чем что-либо еще.

3 голосов
/ 03 января 2010

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

Или вы можете использовать распространение REQUIRES_NEW, но в этом случае Spring создаст другой сеанс для времени жизни новой транзакции. Используйте только если новая транзакция действительно необходима.

Сеанс Hibernate может содержать несколько последовательных транзакций. Поэтому фильтру OSIV не нужно знать, какие транзакции он будет содержать. Фильтр OSIV создает сеанс с FlushMode = MANUAL, и методы транзакции чтения-записи временно изменят его на FlushMode = AUTO. Каждая транзакция будет использовать JDBC-соединение только для чтения или для чтения и записи.

2 голосов
/ 31 октября 2009

Open Session In View не требует, чтобы весь запрос происходил в одной транзакции, это только означает, что Hibernate Session привязан к потоку, обслуживающему запрос, и повторно используется каждый раз, когда что-либо запрашивает сеанс в этом запросе. , Помните, что Session - это как необычная карта, которая поддерживает идентичность всех объектов, отображаемых в своей области, фактические объекты могут быть получены в одной транзакции или в нескольких транзакциях.

Шаблон сеанса на транзакцию на самом деле является альтернативой OSIV. Этот шаблон встречается не часто.

В отношении того, что ваш метод только для чтения вызывает метод чтения-записи, я бы сказал, что вам следует заново подумать, почему вы хотите использовать этот метод только для чтения, когда на самом деле он может записывать данные. Я бы сказал, что либо вы выделяете часть, предназначенную только для чтения, и вызываете метод read-write, вызывающий метод только для чтения, либо просто прекращаете считать его доступным только для чтения (это не так).

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

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