пара вопросов по JPA
От: Trean Беларусь http://axamit.com/
Дата: 26.03.07 11:45
Оценка:
Использую JPA RI (TopLink essentials) в stand-alone J2SE приложении. Программное управление транзакциями и явное создание EntityManager.

1. Как в JPA внести большое (скажем 100k) записей в рамках одной транзакции? Сразу скажу: скорость выполнения операции менее важна, чем объем требуемой памяти (вылетает out of memory error — так как все объекты лежат в контексте). Plain-JDBC не предлагать
2. Чем вызов метода flush отличается от commit и можно ли откатить транзакцию после вызова flush. У меня при явном вызове вызове rollback данные остаются в базе.

З.Ы. С хибернейтом и jdo до этого не работал.

Спасибо
Re: пара вопросов по JPA
От: aka50 Россия  
Дата: 26.03.07 12:03
Оценка:
Здравствуйте, Trean, Вы писали:

T>1. Как в JPA внести большое (скажем 100k) записей в рамках одной транзакции? Сразу скажу: скорость выполнения операции менее важна, чем объем требуемой памяти (вылетает out of memory error — так как все объекты лежат в контексте). Plain-JDBC не предлагать

Ограничивать единоразовое кол-во записей, т.е. реализовать paging...
http://java.sun.com/javaee/5/docs/api/javax/persistence/Query.html#setFirstResult(int)
http://java.sun.com/javaee/5/docs/api/javax/persistence/Query.html#setMaxResults(int)

T>2. Чем вызов метода flush отличается от commit и можно ли откатить транзакцию после вызова flush. У меня при явном вызове вызове rollback данные остаются в базе.

Flush — выполняет накопленные (pending) изменения в виде sql запросов (т.е. например myEntity.setSomeValue(1); em.save(myEntity); не приводит к немедленному update myentity set ... ).
Commit — это явный коммит транзакции... Если данные попадают в бд, возможно не выключeн autocommit
В toplink разве нельзя включить режим логгирования состояний соединений чтобы видеть когда оно коммит делает?
Re[2]: пара вопросов по JPA
От: Blazkowicz Россия  
Дата: 26.03.07 12:21
Оценка:
Здравствуйте, aka50, Вы писали:

A>Ограничивать единоразовое кол-во записей, т.е. реализовать paging...

A>http://java.sun.com/javaee/5/docs/api/javax/persistence/Query.html#setFirstResult(int)
A>http://java.sun.com/javaee/5/docs/api/javax/persistence/Query.html#setMaxResults(int)

А как это работает для update/insert?
Re: пара вопросов по JPA
От: C0s Россия  
Дата: 26.03.07 12:52
Оценка:
Здравствуйте, Trean, Вы писали:

T>1. Как в JPA внести большое (скажем 100k) записей в рамках одной транзакции? Сразу скажу: скорость выполнения операции менее важна, чем объем требуемой памяти (вылетает out of memory error — так как все объекты лежат в контексте). Plain-JDBC не предлагать


не важно, что именно более критично — скорость или память, но наиболее практичным подходом для массовой загрузки данных является использование СУБД-зависимых тулов (типа sqlldr для oracle). любая своя поделка чревата багами и будет уступать как в гибкости, так и по расходу ресурсов (memory + cpu)

дальнейшая обработка загруженных данных более эффективно производится в хранимках, чтобы не таскать туда-сюда данные из СУБД в Java и наоборот

T>2. Чем вызов метода flush отличается от commit и можно ли откатить транзакцию после вызова flush. У меня при явном вызове вызове rollback данные остаются в базе.


autocommit забыл выключить?
Re[3]: пара вопросов по JPA
От: aka50 Россия  
Дата: 26.03.07 12:53
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>А как это работает для update/insert?


"Как в JPA внести большое" прочитал как "вывести"

Для update — только NamedQuery, а вот c insert похоже
только периодическим flash...
Re[2]: пара вопросов по JPA
От: Trean Беларусь http://axamit.com/
Дата: 26.03.07 12:54
Оценка:
Здравствуйте, aka50, Вы писали:

A>Здравствуйте, Trean, Вы писали:


T>>1. Как в JPA внести большое (скажем 100k) записей в рамках одной транзакции? Сразу скажу: скорость выполнения операции менее важна, чем объем требуемой памяти (вылетает out of memory error — так как все объекты лежат в контексте). Plain-JDBC не предлагать

A>Ограничивать единоразовое кол-во записей, т.е. реализовать paging...
A>http://java.sun.com/javaee/5/docs/api/javax/persistence/Query.html#setFirstResult(int)
A>http://java.sun.com/javaee/5/docs/api/javax/persistence/Query.html#setMaxResults(int)

Мне не на чтение, а на запись. Когда я вызываю persist для объектов, они все хранятся в контексте до самого коммита. По спеке вроде flushmode.AUTO по дефолту включен, но OOE вылетает все равно. Мне бы flush + clear бы помогло думаю, но для этого надо разобраться со второй проблемой.

T>>2. Чем вызов метода flush отличается от commit и можно ли откатить транзакцию после вызова flush. У меня при явном вызове вызове rollback данные остаются в базе.

A>Flush — выполняет накопленные (pending) изменения в виде sql запросов (т.е. например myEntity.setSomeValue(1); em.save(myEntity); не приводит к немедленному update myentity set ... ).
A>Commit — это явный коммит транзакции... Если данные попадают в бд, возможно не выключeн autocommit
A>В toplink разве нельзя включить режим логгирования состояний соединений чтобы видеть когда оно коммит делает?

Скачал последний билд с сорсами, включу логгинг посмотрю что происходит, отпишу потом.
Re[2]: пара вопросов по JPA
От: Дмитрий В  
Дата: 26.03.07 13:02
Оценка:
Здравствуйте, aka50, Вы писали:

A>Здравствуйте, Trean, Вы писали:


T>>1. Как в JPA внести большое (скажем 100k) записей в рамках одной транзакции? Сразу скажу: скорость выполнения операции менее важна, чем объем требуемой памяти (вылетает out of memory error — так как все объекты лежат в контексте). Plain-JDBC не предлагать

A>Ограничивать единоразовое кол-во записей, т.е. реализовать paging...
A>http://java.sun.com/javaee/5/docs/api/javax/persistence/Query.html#setFirstResult(int)
A>http://java.sun.com/javaee/5/docs/api/javax/persistence/Query.html#setMaxResults(int)
А как размер всего результата можно узнать?
Тупо смотреть размер результирующего списка или слать запрос типа select count(*)? Оба варианта какие то некрасивые — первый неоптимальный, а второй иногда неудобный в плане реализации...
Re[2]: пара вопросов по JPA
От: Trean Беларусь http://axamit.com/
Дата: 26.03.07 13:07
Оценка:
Здравствуйте, C0s, Вы писали:

C0s>Здравствуйте, Trean, Вы писали:


T>>1. Как в JPA внести большое (скажем 100k) записей в рамках одной транзакции? Сразу скажу: скорость выполнения операции менее важна, чем объем требуемой памяти (вылетает out of memory error — так как все объекты лежат в контексте). Plain-JDBC не предлагать


C0s>не важно, что именно более критично — скорость или память, но наиболее практичным подходом для массовой загрузки данных является использование СУБД-зависимых тулов (типа sqlldr для oracle). любая своя поделка чревата багами и будет уступать как в гибкости, так и по расходу ресурсов (memory + cpu)


Согласен, но я прототип приложения пока пишу для верификации объектной модели, и на данном этапе хотел бы абстрагироваться от конкретного вендора будь-то оракл или mysql. Потом уже можно будет что-то оптимизировать. Мне сейчас важнее разобраться как правильно работать с JPA и в частности с вышеуказанной проблемой.

C0s>дальнейшая обработка загруженных данных более эффективно производится в хранимках, чтобы не таскать туда-сюда данные из СУБД в Java и наоборот


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

T>>2. Чем вызов метода flush отличается от commit и можно ли откатить транзакцию после вызова flush. У меня при явном вызове вызове rollback данные остаются в базе.


C0s>autocommit забыл выключить?


А как его выключить-то, я ж не работаю с соединениями напрямую? Логично чтобы этим занимался EntityManager сам при вызове EntityManager.getTransaction().
Re[3]: пара вопросов по JPA
От: Дмитрий В  
Дата: 26.03.07 13:08
Оценка:
Неудобный в том плане, когда используются Hibernate Criteria — я даже не представляю, как можно найти результат типа count(*)....
Re[4]: пара вопросов по JPA
От: Дмитрий В  
Дата: 26.03.07 13:11
Оценка:
А кажется нашел... Возможно Projections помогут...
Re[3]: пара вопросов по JPA
От: aka50 Россия  
Дата: 26.03.07 13:42
Оценка:
Здравствуйте, Дмитрий В, Вы писали:

ДВ>А как размер всего результата можно узнать?

ДВ>Тупо смотреть размер результирующего списка или слать запрос типа select count(*)? Оба варианта какие то некрасивые — первый неоптимальный, а второй иногда неудобный в плане реализации...

Для jdbc уже обсуждалось: http://rsdn.ru/Forum/Message.aspx?mid=2382815
Автор:
Дата: 26.02.07


Про поддержку этого добра в hibernate можно почитать http://www.hibernate.org/314.html
Re: пара вопросов по JPA
От: Trean Беларусь http://axamit.com/
Дата: 26.03.07 14:14
Оценка:
Здравствуйте, Trean, Вы писали:

T>Использую JPA RI (TopLink essentials) в stand-alone J2SE приложении. Программное управление транзакциями и явное создание EntityManager.


T>1. Как в JPA внести большое (скажем 100k) записей в рамках одной транзакции? Сразу скажу: скорость выполнения операции менее важна, чем объем требуемой памяти (вылетает out of memory error — так как все объекты лежат в контексте). Plain-JDBC не предлагать

T>2. Чем вызов метода flush отличается от commit и можно ли откатить транзакцию после вызова flush. У меня при явном вызове вызове rollback данные остаются в базе.

T>З.Ы. С хибернейтом и jdo до этого не работал.


T>Спасибо


Всем спасибо за советы, виновата моя невнимательность — совершенно упустил из виду что MYISAM не поддерживает транзакции. При переходе на INNODB все работает как часы. Остался вопрос только, как указать в peristense.xml для mysql провайдера свойство, чтобы генерились INNODB таблицы.
Re[2]: пара вопросов по JPA
От: Trean Беларусь http://axamit.com/
Дата: 27.03.07 14:47
Оценка:
Здравствуйте, Trean, Вы писали:

T>Здравствуйте, Trean, Вы писали:


T>>Использую JPA RI (TopLink essentials) в stand-alone J2SE приложении. Программное управление транзакциями и явное создание EntityManager.


T>>1. Как в JPA внести большое (скажем 100k) записей в рамках одной транзакции? Сразу скажу: скорость выполнения операции менее важна, чем объем требуемой памяти (вылетает out of memory error — так как все объекты лежат в контексте). Plain-JDBC не предлагать

T>>2. Чем вызов метода flush отличается от commit и можно ли откатить транзакцию после вызова flush. У меня при явном вызове вызове rollback данные остаются в базе.

T>>З.Ы. С хибернейтом и jdo до этого не работал.


T>>Спасибо


T>Всем спасибо за советы, виновата моя невнимательность — совершенно упустил из виду что MYISAM не поддерживает транзакции. При переходе на INNODB все работает как часы. Остался вопрос только, как указать в peristense.xml для mysql провайдера свойство, чтобы генерились INNODB таблицы.


Что все работает, это я поторопился сказать, память все равно заканчивалась. Вот можно сказать официальный ответ получил от разработчиков топ-линковской имплементации JPA после того как порылся в сорсах (там в одном месте не очищается hashtable при clear):

"Caching provides a benefit for a vast majority of users but TopLinks caching mechanism requires tracking of the objects in the current transaction to ensure the cache contains current information. There is currently no JPA defined mechanism to notify the Persistence Provider that a transaction will contain only inserts so TopLink has to assume that the transaction will include other forms of data modifications. The only way to prevent the out of memory is to keep the transactions moderate in size."

(c) Gordon Yorke

Так что будьте внимательны в любом случае Остался, правда, вопрос почему они создают отдельный запрос, судя по логу, для каждой записи в базу вместо batchUpdate. Спрошу в другой раз. Надо посмотреть Hibernate реализацию к JPA.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.