Хранение больших данных в чанках: Hibernate @OneToMany отношения - PullRequest
1 голос
/ 24 июля 2011

Я использую Hibernate для хранения отношений родитель-потомок, используя @OneToMany с @JoinColumn в течение некоторого времени, это прекрасно работает.

Но теперь я достиг точки, когда общий размер объектов слишком велик, чтобы поместиться в памяти. (например, сейчас есть 3 миллиона дочерних записей). Все записи хранятся в файле, а затем разбираются в объектах Java перед переходом в спящий режим.

Я бы хотел "разбить на части" или "пакетировать" записи, чтобы мне нужно было считывать только часть из них за раз. Мой подход подобен «загрузке коллекции из 10 000 дочерних объектов, сохранению в базе данных (вызов« update »в родительском объекте), очистке дочерней коллекции для освобождения ОЗУ, повтор».

Я хочу, чтобы это работало так:

Iteration 1:  Chunk1 (records 1-10,000) stored
Iteration 2:  Chunk2 (records 10,001-20,000) stored
Iteration 3:  Chunk3 (records 20,001-30,000) stored
etc

Вот где у меня проблемы. Коллекция, которую я сохраняю, меняется с каждой итерацией, что приводит к тому, что hibernate отбрасывает всех старых потомков перед сохранением новых потомков. Вместо того, чтобы сохранить все мои куски, я получаю

Iteration 1: Chunk1 stored
Iteration 2: Chunk1 objects deleted, Chunk 2 stored
Iteration 3: Chunk2 objects deleted, Chunk 3 stored
etc

Итак, в итоге сохраняется только мой последний кусок.

Есть ли способ изменить это поведение? Я читал о пакетной обработке JDBC, но это не совсем то, что я ищу. Я также пытался хранить каждого потомка отдельно, а не через «обновление» родителя, но когда я делаю это, записи потомка сохраняются без указателя на родителя.

Обновление:

Спасибо за быстрый и потрясающий ответ. Отношения не двунаправленные - я постараюсь сделать так. У меня есть устаревший код, который не будет взаимодействовать с изменениями схемы, поэтому я немного ограничен.

Спасибо

1 Ответ

2 голосов
/ 25 июля 2011

Главный вопрос здесь: двунаправленны ли ваши отношения? То есть у вас есть @ManyToOne на дочерней стороне, указывающей назад на родителя?

Если вы это сделаете, эти отношения должны принадлежать дочерней стороне:

// in Parent
@OneToMany(mappedBy="parent")
List<Child> getChildren();

// in Child
@ManyToOne
Parent getParent();

При такой настройке вам НЕ необходимо загрузить все (или, если на то пошло) дочерние элементы в коллекции ваших родителей - вы можете вместо этого загрузить (или создать) дочерние элементы, установить родительские для них конец и сохранить их; Вы, конечно, можете делать это партиями.

Если ваши отношения не двунаправленные, то, основываясь на вашем вопросе, они принадлежат родителю - вам нужно будет сделать его двунаправленным, как показано выше (или однонаправленным, но противоположным к тому, что есть сейчас - см. ниже).

В какой-то отдельной заметке, вам даже нужен @OneToMany на родительской стороне? С 3 миллионами детских записей я не могу себе представить, где это будет полезно.

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