Pytanie o sesję Hibernate.flush()
Chcę zapytać, co tak naprawdę robi metoda flush w następującym przypadku:
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();
}
Czy to oznacza, że po iteracji 20, bufor jest spłukiwany, a następnie 20 przechowywanych obiektów pamięci jest faktycznie zapisywane w bazie danych ?
Czy ktoś może mi wyjaśnić, co się stanie, gdy warunek będzie prawdziwy?4 answers
Z javadoc z Session#flush
:
Wymuś tę sesję do spłukania. Musi być wezwany na koniec jednostki pracy, przed dokonaniem transakcji i zamknięcie sesji (w zależności od flush-mode, transakcja.commit () wywołuje tę metodę).
Flushing jest procesem synchronizacji podstawowych persistent store with persistable stan utrzymany w pamięci.
Innymi słowy, flush
mówi Hibernate do wykonania poleceń SQL potrzebnych do synchronizacji stanu połączenia JDBC ze stanem obiektów przechowywanych w buforze na poziomie sesji. I warunek if (i % 20 == 0)
sprawi, że stanie się to dla każdej i
wielokrotności 20.
Ale nowe instancje Car
będą przechowywane w pamięci podręcznej na poziomie sesji, a dla dużych myList.size()
pożresz całą pamięć i ostatecznie otrzymasz OutOfMemoryException
. Aby uniknąć takiej sytuacji, wzór opisany w dokumentacji ma na celu flush
i clear
sesje w regularnych odstępach czasu (taki sam rozmiar jak rozmiar partii JDBC), aby kontynuować zmiany, a następnie odłączyć instancje, aby mogły być zbierane śmieci: {]}
13.1. Wkładki serii
Gdy nowe obiekty są trwałe flush () a następnie clear () sesji regularnie w celu kontroli wielkości pamięci podręcznej pierwszego poziomu.
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();
Dokumentacja wspomina w tym samym rozdziale, Jak ustawić rozmiar partii JDBC.
Zobacz również
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-18 14:48:55
Zależy od tego, jak skonfigurowany jest FlushMode.
W domyślnej konfiguracji Hibernate próbuje zsynchronizować się z bazą danych w trzech lokalizacjach.
1. before querying data
2. on commiting a transaction
3. explictly calling flush
Jeśli {[1] } jest ustawione jako FlushMode.Ręcznie, programista informuje hibernate, że poradzi sobie z przekazaniem danych do bazy danych.W tej konfiguracji
wywołanie session.flush()
zapisze instancje obiektu w bazie danych.
A session.clear()
wywołanie acutally może być użyte do wyczyszczenia kontekstu persistance.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-18 20:34:38
// 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();
}
Kilka wskazówek dotyczących tego, dlaczego płukanie powinno pasować do wielkości partii Aby włączyć dozowanie, musisz ustawić rozmiar partii jdbc
// In your case
hibernate.jdbc.batch_size =20
Jedną z najczęstszych pułapek w użyciu wsadowania jest to, że jeśli używasz aktualizacji pojedynczego obiektu lub Wstawienia, to idzie dobrze.Ale na wszelki wypadek używasz mutiple obiektów prowadzących do wielu wstawek /aktualizacji, wtedy będziesz musiał jawnie ustawić mechanizm sortowania.
Na przykład
// 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();
}
Tutaj w tym przypadku generowane są dwa sql 1 dla Wstaw w samochodzie 1 do wkładki w akcesorium
Do prawidłowego dozowania należy ustawić
<prop key="hibernate.order_inserts">true</prop>
Aby wszystkie wkładki do samochodu zostały posortowane razem i wszystkie wkładki akcesoriów zostały posortowane together.By w ten sposób będziesz miał wypalanie 20 wstawek w partii, a nie 1 wypalanie sql na raz.
Dla różnych operacji w ramach jednej transakcji, można spojrzeć na http://docs.jboss.org/hibernate/core/3.2/api/org/hibernate/event/def/AbstractFlushingEventListener.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-18 14:18:15
Tak co 20 pętli, SQL jest generowany i wykonywany dla niezapisanych obiektów. Należy również ustawić tryb wsadowy na 20, aby zwiększyć wydajność.