2012-10-27 23 views
6

Używam Hibernuj 4.1.7 i próbuję zaktualizować obiekt, ale nie ma dokumentacji, jak to zrobić. Obecnie robię tak:Aktualizacja hibernacji za pomocą EntityManager

Person person = personDao.getPersonById(1); 
    person.setAge(23); 
    person.setLastname("McName"); 
    person = personDao.update(person); 

W aktualizacji PersonDao wygląda następująco:

public Person update(Person person) { 
     return entityManager.merge(person); 
    } 

W PersonDao getPersonById jest:

public Person getPersonById(int id) { 
     personQuery = entityManager.createNamedQuery("Person.findPerson", Person.class); 
     personQuery.setParameter("id", id); 
     return personQuery.getSingleResult(); 
    } 

Mam także zdefiniowane nazwane zapytania wewnątrz klasy Person i jest tutaj:

@NamedQuery(name="Person.findPerson", query="SELECT p FROM Person p WHERE p.id = :id") 

Korzystając z tego, że moja osoba nie będzie aktualizowana, jak powinienem zaimplementować aktualizację za pomocą hibernacji?

+0

Powyższy kod jest OK, z wyjątkiem, że wywołanie 'personDao.update()' jest zupełnie niepotrzebne, czy wszystko jest prowadzony w ramach jednej transakcji: stan jednostki jest automatycznie wykonany trwały przez JPA/Hibernate w koniec transakcji. Metodę getPersonById można również zredukować do 'em.find (Person.class, id)', co byłoby prostsze i bardziej wydajne, ponieważ nie wykonałoby żadnego zapytania, gdyby jednostka była już wczytana. –

+0

Dodatek: jest to zdecydowanie wyjaśnione w dokumentacji. Zobacz http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html_single/#d5e772 –

Odpowiedz

4

Dwa scenariusze mogą pojawić się dla Ciebie.

Możesz chcieć zmienić właściwość obiektu i tylko tę właściwość.

W takim przypadku należy użyć metody: znajdź, zmodyfikuj, opróżnij, zatwierdz.

em.find(Person.class, person.getId()) 
person.setStatus("ACTIVE"); 
em.commit();//implicitly flushes if flush mode is COMMIT or AUTO. 

Możesz chcieć użyć właściwości obiektów, aby zaktualizować element.

W takim przypadku należy użyć metody: scalanie, opcjonalnie modyfikowanie, opróżnianie, zatwierdzanie.

em.merge(person); 
//modify person if you wish. 
em.commit();//implicitly flushes if flush mode is COMMIT or AUTO. 
+0

Znalazłem moje rozwiązanie, w końcu użyłem entityManager.getTrasaction(). Begin(); osoba = entityManager.find (Person.class, id); entityManager.merge (osoba); // Modyfikuj dane osoby entityManager.getTransaction(). Commit(); – Timo

+0

Cieszę się, że znalazłeś rozwiązanie. Jeśli id ​​użyty podczas find (Person.class, id) to person.id użyte podczas scalania (osoby), scalenie może nie być konieczne. Po znalezieniu jednostka jest zarządzana i można modyfikować i zatwierdzać zmiany. – dseibert

0

Nie wiem co masz dokładnie pytać, ale w sposób, Person.getPersonById(int id) można uprościć kod z następujących czynności:

return entityManager.find(Person.class, id); 
1

Hibernate, a także inne implementacje JPA automatycznie zarządzać stan podmiotów i zapisz go w bazie danych, jeśli modyfikacja jest zawarta w transakcji. Nie trzeba jawnie wywoływać metod: merge lub update.

Jeśli używasz transakcji zasobów lokalnego (nie zarządzanych przez menedżera transakcji JTA) spróbować czegoś takiego:

EntityTransaction tx = entityManager.getTransaction(); 
tx.begin(); 
Person person = personDao.getPersonById(1); 
person.setAge(23); 
person.setLastname("McName"); 
tx.commit(); 

a wszystkie zmiany zostaną automatycznie zapisane w bazie danych.

Jeśli używasz JTA, musisz zaznaczyć granice transakcji w inny sposób, na przykład za pomocą adnotacji Spring AOP @Transactional.

+0

Używam hsqldb (resource-local) i używając tego kodu otrzymuję wyjątek: org.hibernate. PersistentObjectException: odłączona jednostka przekazana do trwałości: com.application.model.Person – Timo

+0

Prawdopodobnie używasz dwóch różnych instancji EntityManager. – Jarek