Подтвердить что ты не робот

Вопрос о Hibernate session.flush()

Я хочу узнать о том, что на самом деле делает метод flush в следующем случае:

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 сохраненных объектов памяти фактически сохраняются в базе данных?

Может кто-нибудь, пожалуйста, объясните мне, что произойдет, когда условие будет истинным.

4b9b3361

Ответ 1

Из javadoc Session#flush:

Принудительный сеанс. Должно быть называемый в конце единицы работы, перед совершением транзакции и закрытие сеанса (в зависимости от флеш-режим, Transaction.commit()вызывает этот метод).

Промывка - это процесс синхронизации основных постоянный магазин с устойчивыми сохраненное в памяти.

Другими словами, flush сообщает Hibernate выполнить инструкции SQL, необходимые для синхронизации состояния соединения JDBC с состоянием объектов, хранящихся в кеше уровня сеанса. И условие if (i % 20 == 0) сделает это для каждого i, кратного 20.

Но, тем не менее, новые экземпляры Car будут храниться в кеше уровня сеанса, а для больших myList.size() вы будете есть всю память и, в конечном итоге, получите OutOfMemoryException. Чтобы избежать этой ситуации, шаблон, описанный в документации, соответствует flush И clear сеансу с регулярными интервалами (размер, размер партии JDBC), чтобы сохранить изменения, а затем отсоединить экземпляры так что они могут быть собраны мусором:

13.1. Пакетные вставки

При создании новых объектов flush(), а затем очистить() сеанс регулярно, чтобы контролировать размер кеша первого уровня.

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

for ( int i=0; i<100000; i++ ) {
    Customer customer = new Customer(.....);
    session.save(customer);
    if ( i % 20 == 0 ) { //20, same as the JDBC batch size
        //flush a batch of inserts and release memory:
        session.flush();
        session.clear();
    }
}

tx.commit();
session.close();

Документация упоминает в той же главе, как установить размер партии JDBC.

См. также

Ответ 2

Зависит от того, как настроен FlushMode.

В конфигурации по умолчанию Hibernate пытается синхронизировать с базой данных в трех местах.

1. before querying data
2. on commiting a transaction
3. explictly calling flush

Если параметр FlushMode задан как FlushMode.Manual, программист информирует спящий режим, что он будет обрабатывать, когда передавать данные в базу данных. В этой конфигурации вызов session.flush() сохранит экземпляры объектов в базе данных.

A session.clear() вызов acutally может использоваться для очистки контекста стойкости.

Ответ 3

// 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 кв. стрельбе за раз.

Для разных операций в рамках одной транзакции вы можете посмотреть http://docs.jboss.org/hibernate/core/3.2/api/org/hibernate/event/def/AbstractFlushingEventListener.html

Ответ 4

Да каждые 20 циклов, sql генерируется и выполняется для несохраненных объектов. Также вы должны установить режим партии до 20 для повышения производительности.