Я хочу справиться о том, что на самом деле метод сброса делает в следующем случае:
for (int i = 0; i < myList.size(); i++) {
Car c = new Car( car.get(i).getId(),car.get(i).getName() );
getCurrentSession().save(c);
if (i % 20 == 0)
getCurrentSession().flush();
}
Это означает, что после повторения 20, кэш сбрасывается, и затем 20 сохраненных объектов памяти на самом деле сохраняются в базе данных?
Может кто-то объяснять мне, что произойдет, когда условие будет верно.
Из javadoc Session # flush
:
Принудительно сбросить этот сеанс. Должно быть вызывается в конце единицы работы, перед совершением транзакции и закрытие сеанса (в зависимости от flush-mode , Transaction.commit () вызывает этот метод).
Сброс - это процесс синхронизации базового постоянное хранилище с постоянным состояние хранится в памяти.
Другими словами, flush
предписывает Hibernate выполнять операторы SQL, необходимые для синхронизации состояния соединения JDBC с состоянием объектов, хранящихся в кэше уровня сеанса. И условие if (i% 20 == 0)
заставит это выполняться для каждого i
кратного 20.
Но, тем не менее, новый Car
] будут храниться в кэше уровня сеанса, а для большого myList.size ()
вы съедите всю память и в конечном итоге получите исключение OutOfMemoryException
. Чтобы избежать этой ситуации, шаблон, описанный в документации, состоит в том, чтобы очистить
И очистить
сеанс через равные промежутки времени (того же размера, что и размер пакета JDBC), чтобы сохранить изменения, а затем отсоединить экземпляров, чтобы их можно было собрать сборщиком мусора:
13.1. Пакетная вставка
При создании постоянных новых объектов flush (), а затем очистить () сеанс регулярно, чтобы контролировать размер кеш-памяти первого уровня.
Сессия session = sessionFactory.openSession (); Транзакция tx = session.beginTransaction (); for (int i = 0; i <100000; i ++) { Клиент customer = новый клиент (.....); сеанс.сохранить (заказчик); if (i% 20 == 0) {// 20, то же, что и размер пакета JDBC // сбрасываем пакет вставок и освобождаем память: session.flush (); session.clear (); } } tx.commit (); session.close ();
В той же главе документации упоминается, как установить размер пакета JDBC.
Зависит от того, как настроен FlushMode.
В конфигурации по умолчанию Hibernate пытается синхронизироваться с базой данных в трех местах.
1. before querying data
2. on commiting a transaction
3. explictly calling flush
Если FlushMode
установлен как FlushMode.Manual, программист сообщает спящему режиму, что он / она будет обрабатывать, когда передавать данные в базу данных. В этой конфигурации
вызов session.flush ()
сохранит экземпляры объекта в базе данных.
Вызов session.clear ()
фактически может использоваться для очистки контекста устойчивости.
// Assume List to be of 50
for (int i = 0; i < 50 ; i++) {
Car c = new Car( car.get(i).getId(),car.get(i).getName() );
getCurrentSession().save(c);
// 20 car Objects which are saved in memory syncronizes with DB
if (i % 20 == 0)
getCurrentSession().flush();
}
Еще несколько указателей относительно того, почему промывка должна соответствовать размеру пакета Чтобы включить пакетную обработку, вам необходимо установить размер пакета jdbc
// In your case
hibernate.jdbc.batch_size =20
. Одна из распространенных ошибок при использовании пакетной обработки - если вы используете обновление одного объекта или вставку, это нормально. вы используете несколько объектов, ведущих к множеству вставок / обновлений, тогда вам нужно будет явно установить механизм сортировки.
Например
// Assume List to be of 50
for (int i = 0; i < 50 ; i++) {
Car c = new Car( car.get(i).getId(),car.get(i).getName() );
// Adding accessory also in the card here
Accessories a=new Accessories("I am new one");
c.add(a);
// Now you got two entities to be persisted . car and accessory
// Two SQL inserts
getCurrentSession().save(c);
// 20 car Objects which are saved in memory syncronizes with DB
// Flush here clears the car objects from 1st level JVM cache
if (i % 20 == 0)
getCurrentSession().flush();
getCurrentSession().clear();
}
Вот в этом случае генерируются два sql 1 для вставки в машину 1 для вставки в принадлежность
Для правильного дозирования вам необходимо настроить
<prop key="hibernate.order_inserts">true</prop>
так, чтобы все вставки для автомобиля были отсортированы вместе, а все вставки принадлежностей - вместе. Таким образом у вас будет 20 вставок, стреляющих за один цикл. партия, а не запуск 1 sql за раз.
Для различных операций в рамках одной транзакции вы можете посмотреть http://docs.jboss.org/hibernate/core/3.2/api/org/hibernate/event/def/AbstractFlushingEventListener.html
Да, каждые 20 циклов sql создается и выполняется для несохраненных объектов. Вам также следует установить пакетный режим на 20, чтобы повысить производительность.