Вопрос о В спящем режиме session.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 сохраненных объектов памяти на самом деле сохраняются в базе данных?

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

28
задан matt b 18 July 2010 в 16:25
поделиться

4 ответа

Из 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.

См. Также

51
ответ дан 28 November 2019 в 03:08
поделиться

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

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

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

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

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

2
ответ дан 28 November 2019 в 03:08
поделиться
// 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

1
ответ дан 28 November 2019 в 03:08
поделиться

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

0
ответ дан 28 November 2019 в 03:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: