Можете ли вы иметь несколько транзакций на одном сеансе Hibernate?
Есть ли у вас несколько транзакций в одном сеансе Hibernate?
Я не понимаю, насколько это желательно. В моем коде у меня есть длинный поток и берет элементы из очереди блокировки, в зависимости от того, что находится в очереди, может потребоваться создать и сохранить объект спящего режима, иначе ему может ничего не понадобиться.
Каждый элемент отличается, поэтому, если элемент 1 сохранен, а элемент 2 не может сохранить причину, по которой я не хочу, чтобы предотвратить добавление элемента 1 в базу данных.
Таким образом, самый простой способ сделать это - для каждого элемента, который необходимо создать для создания нового сеанса, открытия транзакции, сохранения нового объекта, фиксации транзакции, закрытия сеанса
Тем не менее, это означает, что для каждого элемента создается новый сеанс, который, по-видимому, противоречит Hibernates собственным рекомендациям, чтобы не выполнять шаблон за каждый запрос. Поэтому моя альтернатива заключалась в том, чтобы создать один сеанс в потоке, а затем просто открыть и перенести новую транзакцию по мере необходимости, чтобы создать новый объект. Но я не видел примеров такого подхода, и я не уверен, действительно ли это работает.
Ответы
Ответ 1
Шаблон сеанса за запрос использует одно соединение JDBC для каждого сеанса, если вы выполняете локальные транзакции. Для JTA соединения будут агрессивно выпущены после того, как каждое утверждение будет только для следующего утверждения.
API транзакций Hibernate делегирует начало/фиксацию/откат JDBC-соединения для локальных транзакций и связанное с ним UserTransaction для JTA. Таким образом, вы можете запускать несколько транзакций на одном сеансе Hibernate, но есть улов. После того, как вы выбрали исключение, вы больше не сможете повторно использовать этот сеанс.
Мой совет - разделить и победить. Просто разделите все элементы, создайте объект Command для каждого из них и отправьте их в ExecutorService#invokeAll
. Используйте возвращенный список для повторения и вызовите Future#get()
, чтобы убедиться, что исходный поток ждет после завершения всех пакетных заданий.
ExecutorService
будет выполнять все команды одновременно, и каждая команда должна использовать Службу, которая использует свой собственный @Transaction
. Поскольку транзакции связаны потоками, вы будете иметь все пакетные задания, выполняемые изолированно.
Ответ 2
Очевидно, вы можете. Спящий сеанс - это более или менее соединение с базой данных и кеш для объектов базы данных. И вы можете иметь несколько последовательных транзакций в одном соединении с базой данных. Более того, когда вы используете пул соединений, соединение не закрывается, а перерабатывается.
Нужно ли вам или нет, это повторное использование объектов из сеанса. Если есть хорошие шансы, но вы можете повторно использовать объекты, которые предыдущая транзакция поставила в сеанс, вы должны оставить один сеанс для нескольких транзакций. Но если после того, как объект был зафиксирован, он никогда не будет повторно использован, конечно лучше закрыть сеанс и снова открыть новый или просто очистить его.
Как это сделать:
Если у вас есть объект Session, вы создаете транзакции с помощью:
Transaction transaction;
transaction = session.beginTransaction();
... (operations in the context of transaction)
transaction.commit();
... (other commands outside of any transaction)
transaction = session.beginTransaction();
... (and so on and so forth ...)
Ответ 3
Из документации спящего режима
"Сессия - это недорогой, не-потоковый объект, который следует использовать один раз, а затем отбрасывать для: одного запроса, разговора или одной единицы работы. Сессия не получит соединение JDBC или источник данных, если он не понадобится. Он не будет использовать ресурсы до тех пор, пока не будет использован".
поэтому, если вы создаете сеансы снова и снова, это не повредит системе. Если вы продолжаете сеанс слишком долго, это может создать проблемы, так как сеанс не является потокобезопасным. На мой взгляд, вы простое решение - лучшее ". Таким образом, самый простой способ сделать это - для каждого элемента, который необходимо создать для создания нового сеанс, открытая транзакция, сохранение нового объекта, фиксация транзакции, закрытие сеанса"
Кстати, если вы создаете одиночную запись чего-либо, вам не нужна транзакция слишком много. создание отдельной записи по сути является "все или ничего", для которой мы используем транзакцию
Ответ 4
Короткий ответ - да, вы можете использовать тот же сеанс для транзакции. Взгляните на org.hibernate.Transaction., У него есть необходимый метод для управления транзакцией.
Ответ 5
package hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
class Tester {
public static void main(String[] args) {
SessionFactory sf = new org.hibernate.cfg.Configuration().configure().buildSessionFactory(new StandardServiceRegistryBuilder().configure().build());
Session session = sf.openSession();
session.beginTransaction();
Student student = new Student();
student.setName("Mohammad Faizan");
student.setRollNo(1309114040);
session.save(student);
session.getTransaction().commit();
session.getTransaction().begin();
session.load(Student.class,23);
student.setName("New Name");
student.setRollNo(123);
session.update(student);
session.getTransaction().commit();
session.close();
}
}