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?
Author: matt b, 2010-07-18

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ż

 50
Author: Pascal Thivent,
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.

 2
Author: frictionlesspulley,
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

 1
Author: Manish Singh,
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ść.

 0
Author: ,
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 09:24:08