2013-08-13 15 views
12

Próbuję użyć Hibernate dla aplikacji wielowątkowej, w której każdy wątek pobiera obiekt i próbuje wstawić go do tabeli. Mój kod wygląda jak poniżej. Mam lokalne obiekty sesji hibernacji na wątek i w każdym InsertData robię beginTransaction i zatwierdzam.Jak korzystać z Hibernate w aplikacji wielowątkowej?

Problem jestem stoi to, że wiele razy otrzymuję „org.hibernate.TransactionException: zagnieżdżone transakcje nie są obsługiwane”

Ponieważ jestem nowy do hibernacji nie wiem, czy to co robie jest prawidłowa lub nie? Proszę dać mi znać, jaki jest właściwy sposób korzystania z hibernacji w aplikacji wielowątkowej i jak uniknąć wspomnianego wyżej wyjątku.

Dzięki

public class Worker extends Thread { 
private Session session = null; 

Worker() { 
    SessionFactory sf = HibernateUtil.getSessionFactory(); // Singleton 
    session = sf.openSession(); 
    session.setFlushMode(FlushMode.ALWAYS); 
} 

public void run() { 
    // Some loop which will run thousand of times 
    for (....) 
    { 
     InsertData(b); 
    } 
    session.close(); 
} 

// BlogPost Table has (pk = id AutoGenerated), dateTime, blogdescription etc. 
private void InsertData(BlogPost b) { 
    session.beginTransaction(); 
    Long id = (Long) session.save(b); 
    b.setId(id); 
    session.getTransaction().commit(); 
} 
} 

Mój plik hibernacji config został c3p0.min_size=10 i c3p0.max_size=20

+0

Czy to ma być 'b.setId()'? –

+0

Tak, właśnie to poprawiłem. Podczas próby utworzenia minimalnego przykładu mojego rzeczywistego kodu wystąpił typo. – Rahul

Odpowiedz

10

Z sesji obiektów-per-wątku, tak długo jak nie są udostępnianie obiektów sesji między wielu wątków, będzie dobrze .

Otrzymany błąd nie jest związany z użytkowaniem wielowątkowym ani z zarządzaniem sesją. Twoje użycie numeru session.save() oraz jawne ustawienie identyfikatora nie jest całkiem poprawne.

Trudno powiedzieć, czy jest to trudne do odczytania, ale jeśli powiedzieliście Państwo Hibernate, aby użyć pola id jako klucza podstawowego i używacie natywnego generatora dla kluczy podstawowych, wszystko, co musisz zrobić, to to, :

session.beginTransaction(); 
session.persist(b); 
session.flush(); // only needed if flush mode is "manual" 
session.getTransaction().commit(); 

Hibernate będzie wypełnić ID dla ciebie, persist() spowoduje wkładka wydarzy w granicach transakcji (save() nie dba o transakcjach). Jeśli tryb spłukiwania nie jest ustawiony na ręczny, nie musisz dzwonić pod numer flush(), ponieważ zajmie się nim Transaction.commit().

Pamiętaj, że w przypadku persist() nie można zagwarantować, że identyfikator BlogPost będzie ustawiony, dopóki sesja nie zostanie opróżniona, co jest w porządku dla twojego użycia tutaj.

do obsługi błędów wdzięcznie:

try { 
    session.beginTransaction(); 
    try { 
     session.persist(b); 
     session.flush(); // only needed if flush mode is "manual" 
     session.getTransaction().commit(); 
    } catch (Exception x) { 
     session.getTransaction().rollback(); 
     // log the error 
    } 
} catch (Exception x) { 
    // log the error 
} 

Nawiasem mówiąc, ja sugerując co BlogPost.setId() prywatny, czy pakiet widoczne. Najprawdopodobniej jest to błąd implementacji, jeśli inna klasa jawnie ustawi identyfikator (ponownie zakładając generator natywny, a id jako klucz podstawowy).

+1

Dzięki Jason, nie miałem rollback(), dzięki czemu poprzedni wyjątek pozostawiał transakcję otwartą dla wątku, a kolejna wartość beginTransation była używana do rzucania "TransactionException". – Rahul

Powiązane problemy