Является ли инфраструктура JPA/EJB3 стандартным способом работы с вставкой в пакет...? Мы используем hibernate для платформы persistence, поэтому я могу вернуться на сеанс Hibernate и использовать комбинацию session.save()/session.flush() для достижения пакетной вставки. Но хотелось бы знать, поддерживает ли EJB3 это...
Пакетные вставки с JPA/EJB3
Ответ 1
Ни JPA, ни Hibernate не поддерживают особую поддержку пакетных вставок, и идиома для пакетных вставок с JPA будет такой же, как с Hibernate:
EntityManager em = ...;
EntityTransaction tx = em.getTransaction();
tx.begin();
for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
em.persist(customer);
if ( i % 20 == 0 ) { //20, same as the JDBC batch size
//flush a batch of inserts and release memory:
em.flush();
em.clear();
}
}
tx.commit();
session.close();
Использование проприетарного API Hibernate в этом случае не дает никаких преимуществ IMO.
Ссылки
- Спецификация JPA 1.0
- Раздел 4.10 "Операции массового обновления и удаления"
- Справочное руководство по Hibernate Core
Ответ 2
Для спящего режима, в частности, вся глава 13 основного руководства объясняет методы.
Но вы говорите, что хотите использовать EJB-метод через Hibernate, поэтому документация менеджера объектов также содержит главу о здесь. Я предлагаю вам прочитать как (ядро, так и менеджер сущностей).
В EJB это просто об использовании EJB-QL (с некоторыми ограничениями). Hibernate предоставляет больше механики, хотя, если вам нужна большая гибкость.
Ответ 3
С номером средних записей вы можете использовать этот способ:
em.getTransaction().begin();
for (int i = 1; i <= 100000; i++) {
Point point = new Point(i, i);
em.persist(point);
if ((i % 10000) == 0) {
em.flush();
em.clear();
}
}
em.getTransaction().commit();
Но с большим количеством записей вы должны выполнить эту задачу в нескольких транзакциях:
em.getTransaction().begin();
for (int i = 1; i <= 1000000; i++) {
Point point = new Point(i, i);
em.persist(point);
if ((i % 10000) == 0) {
em.getTransaction().commit();
em.clear();
em.getTransaction().begin();
}
}
em.getTransaction().commit();
Ссылка: JPA Batch Store
Ответ 4
Да, вы можете откатиться к своей реализации JPA, если хотите, чтобы вы определили этот элемент управления.
JPA 1.0 богата на EL-HQL, но облегчает поддержку API Criteria, однако это было рассмотрено в версии 2.0.
Session session = (Session) entityManager.getDelegate();
session.setFlushMode(FlushMode.MANUAL);
Ответ 5
Паскаль
В вашем примере, чтобы вставить 100000 записей, это делается в рамках одной транзакции, поскольку commit() вызывается только в конце. Он оказывает много давления на базу данных? Кроме того, в случае отката стоимость будет слишком большой.
Будет ли лучше работать следующий подход?
EntityManager em = ...;
for ( int i=0; i<100000; i++ ) {
if(!em.getTransaction().isActive()) {
em.getTransaction().begin();
}
Customer customer = new Customer(.....);
em.persist(customer);
if ((i+1) % 20 == 0 ) { //20, same as the JDBC batch size
//flush and commit of inserts and release memory:
em.getTransaction().commit();
em.clear();
}
}
session.close();