В сопроводительном комментарии к вопросу говорится -
«Вызывающий компонент не имеет состояния и выполняется в течение многих секунд. Данные не отображаются другим пользователям базы данных до тех пор, пока не завершится работа компонента».
Это описанное поведение не имеет ничего общего с очисткой контекста постоянства, связанного с EntityManager.Это во многом связано с уровнем изоляции транзакции, связанной с транзакцией.Транзакция, связанная с сессионным компонентом без сохранения состояния (SLSB), фактически фиксирует данные в базе данных, только при возврате из метода bean-компонента, поскольку каждый метод SLSB может быть связан с атрибутом транзакции по умолчанию REQUIRED
(который использует существующую транзакцию или запускается).новенький);В результате получается, что транзакция завершается с помощью отката в методе SLSB или с помощью коммита при возврате из метода.
Это поведение влияет на операции чтения, выполняемые другими клиентами и транзакциями, поскольку итоговый результат зависит от изоляции.уровень текущей соответствующей транзакции, который, в свою очередь, зависит от уровня изоляции, указанного в пуле соединений с базой данных.Для большинства баз данных и связанных пулов соединений уровень изоляции транзакции составляет READ COMMITTED
, и поэтому другие транзакции могут читать только данные, зафиксированные соответствующей транзакцией (т.е. при возврате метода SLSB).Это желательное поведение в большинстве случаев, поскольку вы не хотите читать данные, которые не были переданы (и впоследствии могут быть откатаны), что может привести к грязному чтению.
Если вы намереваетесь выполнить грязное чтение,Вы должны сконфигурировать пул соединений JDBC, чтобы разрешить грязное чтение, или, другими словами, установить уровень изоляции транзакции для пула READ UNCOMMITTED
.Изменения конфигурации будут варьироваться от контейнера к контейнеру, а также будут зависеть от поддержки уровня изоляции READ UNCOMMITTED
базой данных;Например, Oracle не позволяет вам установить уровень изоляции READ UNCOMMITTED
и может установить для него следующий более высокий уровень изоляции, поддерживаемый им (READ COMMITTED
).
Если вы хотите избежать обмана вокругс уровнями изоляции транзакций рассмотрите возможность разделения вызовов методов на несколько транзакций.Этого можно добиться, создав новый бизнес-метод в отдельной SLSB, который требует создания новой транзакции при каждом вызове (REQUIRES_NEW
).Пример псевдокода описан ниже:
@Stateless
@Local(X.class)
public class SLSBX implements X {
@EJB Y y;
@TransactionAttribute(TransactionAttributeType.REQUIRED) // start a new transaction to do work
public void sampleMethod() {
// suspends the existing transaction on invoking Y.anotherSampleMethod()
Y.anotherSampleMethod();
// continue doing work in the current transaction. Work done in anotherSampleMethod() would have either committed or rolled back.
}
}
@Stateless
@Local(Y.class)
public class SLSBY implements Y {
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) // Suspends the existing transaction and creates a new transaction that terminates on method return
public void anotherSampleMethod() {
// do some stuff
}
}
Этот подход, конечно, рекомендуется, только если деловая природа транзакции допускает принятие такого подхода.Как правило, все реальные бизнес-операции, являющиеся частью бизнес-транзакции, необходимо включить в реальную транзакцию.