Сплячий режим: flush () і commit ()


79

Чи є гарною практикою телефонувати org.hibernate.Session.flush()окремо?

Як сказано в org.hibernate.Sessionдокументах,

Потрібно викликати в кінці одиниці роботи, перед здійсненням транзакції та закриттям сеансу (залежно від режиму змиву, Transaction.commit () викликає цей метод).

Не могли б ви пояснити мету flush()чіткого дзвінка, якщо org.hibernate.Transaction.commit()це вже зробите?


Ви можете ін’єктувати sessionFactoryвикористання @Transactionalанотації, якщо ви заглянули в неї. Вам не знадобиться ваш код для транзакцій скрізь, а потім (в деяких ситуаціях це потрібно).
Лев

Я щойно зіткнувся з цікавою ситуацією у своєму коді, мені довелося об’єднати сутність, яка вже мала ідентифікатор, згенерований із клієнтської програми, а потім оновити ту саму сутність, щоб отримати поля, створені в базі даних, такі як дата створення та модифікації. Без виклику session.flush () він викине об’єкт, який не знайдено, виняток, оскільки виклик злиття іноді ігнорується до кінця транзакції, коли я додаю змив відразу після виклику злиття, він змушує сплячий режим робити фактичний запит, а потім оновлюючи об'єкт працює, тому що тепер він існує в базі даних!
Japheth Ongeri - inkalimeva

Відповіді:


98

У посібнику Hibernate ви можете побачити цей приклад

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();

Без виклику методу змиву ваш кеш першого рівня видасть OutOfMemoryException

Також ви можете подивитися цей пост про змивання


не могли б ви дати посилання на цю статтю?
bsiamionau

5
Ця відповідь дає конкретний випадок, коли є гарною ідеєю чітко називати флеш, але я не думаю, що він стосується загального питання, чи завжди потрібно це робити.
Дейв Л.

Привіт @KorayTugay. Я довго не маю досвіду роботи з новими версіями сплячого режиму. Але раніше без чистоти ви могли отримати несподівані результати. Тож я пропоную спробувати різні підходи або навіть перевірити останню документацію
Олексій Булгак

80

flush()синхронізує вашу базу даних із поточним станом об’єкта / об’єктів, що зберігаються в пам’яті, але транзакцію не здійснює. Отже, якщо ви отримаєте будь-який виняток після того, як flush()буде викликано, тоді транзакція буде повернута назад. Ви можете синхронізувати свою базу даних з невеликими шматками даних, використовуючи flush()замість того, щоб фіксувати великі дані одночасно, commit()і стикаєтесь із ризиком отримати OutOfMemoryException.

commit()зробить дані, що зберігаються в базі даних, постійними. Ви не можете відмовити свою транзакцію після commit()успіху.


55

Одним із найпоширеніших випадків явного змивання є створення нової постійної сутності, і ви хочете, щоб у неї був сформований і призначений йому штучний первинний ключ, щоб ви могли використовувати його пізніше в тій самій транзакції. У цьому випадку виклик флешу призведе до того, що вашій особі буде надано ідентифікатор.

Інший випадок - якщо в кеш-пам’яті 1-го рівня є багато речей, і ви хочете періодично очищати це (з метою зменшення обсягу пам’яті, що використовується кешем), але ви все одно хочете зробити все це разом . Це той випадок, який охоплює відповідь Олексія .


1
Якщо ви хочете негайно отримати доступ до сформованого ПК, я вважаю, вам також потрібно зателефонувати.refresh(...)
Сем Беррі

12

flush();Промивання - це процес синхронізації основного постійного сховища зі стійким станом, що зберігається в пам'яті. Він буде оновлювати або вставляти у ваші таблиці в поточній транзакції, але може не фіксувати ці зміни.

Вам потрібно промити пакетну обробку, інакше це може дати OutOfMemoryException.

Commit();Фіксація зробить фіксацію бази даних. Коли у вас є збережений об’єкт і ви змінюєте на ньому значення, він забруднюється, і режим глибокого сну повинен стерти ці зміни на ваш шар стійкості. Отже, вам слід здійснити, але це також закінчує одиницю роботи ( transaction.commit()).


8

Зазвичай не рекомендується чітко викликати флеш, якщо це не потрібно. Hibernate зазвичай автоматично викликає Flush в кінці транзакції, і ми повинні дозволити йому це зробити. Зараз є деякі випадки, коли вам може бути потрібно явно викликати змив, коли друге завдання залежить від результату першого завдання стійкості, причому обидва знаходяться всередині однієї транзакції.

Наприклад, вам може знадобитися зберегти нову сутність, а потім використовувати ідентифікатор цієї сутності, щоб виконати якесь інше завдання всередині тієї самої транзакції, у такому випадку потрібно явно очистити сутність спочатку.

@Transactional
void someServiceMethod(Entity entity){
    em.persist(entity); 
    em.flush() //need to explicitly flush in order to use id in next statement
    doSomeThingElse(entity.getId());    
}

Також зауважте, що явне змивання не спричиняє фіксацію бази даних, фіксація бази даних виконується лише в кінці транзакції, тому, якщо після виклику флеш-помилки виникає помилка виконання, зміни все одно повертаються.


4

За замовчуванням режим змиву - АВТО, що означає, що: "Сеанс іноді змивається перед виконанням запиту, щоб гарантувати, що запити ніколи не повертають застарілий стан", але більшу частину часу сеанс змивається, коли ви вносите зміни. Виклик методу змивання вручну корисний, коли ви використовуєте FlushMode = MANUAL або хочете зробити якусь оптимізацію. Але я ніколи цього не робив, тому не можу дати вам практичних порад.


2

session. Але commit () він буде зберігати дані в базі даних, якщо ми зберігаємо більший обсяг даних, то, можливо, є шанс вийти з винятків пам'яті, як у програмі JDBC у темі Зберегти точку

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.