2012-02-03 11 views
5

Mam aplikację piaskownicy Seam 3 przy użyciu JBoss 7, Hibernate jako domyślną implementację JPA i jako JSF jako interfejs WWW.JPA/Hibernate emituje bez aktualizacji przy zatwierdzaniu w środowisku EJB/Seam

Mam problem, że SQL UPDATE jest domyślnie połknięta.

Moja Stateful EJB w zakresie konwersacji utrzymuje rozszerzony scoped EntityManager i jeden podmiot, Container Managed Transakcje (wymaga nowy)

  1. EntityManager zostaje wstrzyknięty
  2. EJB używa EM załadować podmiotu i utrzymuje to w polu
  3. aplikacja JSF ma dostęp do EJB i jego podmiot, zmienia polu String
  4. Calles aplikacji JSF „Zapisz” metody w EJB
  5. w save() Sprawdzam, czy pole Entities zostało zmienione -> zostało poprawnie zmienione
  6. Nic więcej nie robię, kontener zatwierdza transakcję po zakończeniu save().
  7. Problem: Nie wykonano aktualizacji SQL w stosunku do bazy danych.

Jeśli mogę przedłużyć save() przez:

a) entityManager.contains (podmiot) Aktualizacja jest wykonywane zgodnie z oczekiwaniami (wynik jest "true")

LUB

b) entityManager.persist (encja) UPDATE jest wykonywana zgodnie z oczekiwaniami.

P: O ile rozumiem, specyfikacje ani a), ani b) nie powinny być wymagane, ponieważ Jednostka pozostaje zarządzana podczas całego procesu. Nie rozumiem, dlaczego a) ma wpływ na zapisywanie. Potrafię zobrazować b) ma wpływ na zapisywanie, ale nie powinno być wymagane, czy powinno?

Wszelkie wyjaśnienia są mile widziane.

Oto moja EJB:

@Named 
@ConversationScoped 
@Stateful 
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
public class LanguageBean { 

    @PersistenceContext(type = PersistenceContextType.EXTENDED) 
    private EntityManager em; 
    @Inject 
    private UserTransaction transaction; 

    private Language value; 

    @Inject 
    Conversation conversation; 

    public LanguageBean() { 
     super(); 
    } 

    @Begin 
    public void selectLanguage(Long anId) { 
     conversation.setTimeout(10 * 60 * 1000); 
     if (anId != null) { 
      value = em.find(Language.class, anId); 
     } 
    } 

    @BeforeCompletion 
    public void transactionComplete(){ 
     System.out.println("transactionComplete"); 
    } 

    public Language getValue() { 
     return value; 
    } 

    @Produces 
    @Named 
    @ConversationScoped 
    public Language getLanguage() { 
     return getValue(); 
    } 

    public void setValue(Language aValue) { 
     value = aValue; 
    } 

    @End 
    public String save() { 
//  displays the changed attribute: 
     System.out.println("save code: "+value.getCode()); 

//  why is either this required: 
//  boolean tempContains = em.contains(value); 
//  System.out.println("managed: "+tempContains); 

//  or: why is persist required: 
     em.persist(value); 
     return "languages?faces-redirect=true"; 
    } 

    @End 
    public String cancel() throws SystemException { 
     transaction.setRollbackOnly(); 
     return "languages?faces-redirect=true"; 
    } 

} 
+0

okazało się, entityManager.flush() rozwiązuje również problem. Ale nie rozumiem, dlaczego wydaje się to wymagane. Ze specyfikacji JPA: "Po zatwierdzeniu transakcji JTA dostawca musi przepłukać cały zmodyfikowany stan obiektu do bazy danych ." – user1187037

+0

może gdzieś w FlushMode sesji hibernacji jest ustawiona na none? – Firo

Odpowiedz

0

Spróbuj dodać @Remove adnotacji na metodach adnotacjami przez @End.

Moim zdaniem, adnotacja @End nie powoduje zniszczenia fasoli. Kontekst utrwalania jest aktywny nawet po wykonaniu save(), a jego zawartość nie może zostać przepuszczona do bazy danych.

1

Moje doświadczenie jest w dużej mierze związane z łączem 2, ale powinno w tym przypadku mieć zastosowanie.

Sesja konwersacji i sesji JPA jest odsprzęgana w szwie z tego prostego powodu, że zakończenie konwersacji może nie spowodować zapisania obiektu.

Na przykład akcja anulować na długim biegu rozmowy zakończy rozmowę (ponieważ nie ma żadnego powodu, aby utrzymać rozmowę już)

Zważywszy, że robisz wycofywania na anulować w przykładzie, to Wydawałoby się logiczne, że musisz wywołać kolor zgodnie z sugestią @ user1187037 (teoretycznie zatwierdzenie, ale nie sądzę, aby było to dozwolone)

Myślę, że mogła istnieć konfiguracja, którą można ustawić tak, aby się spłukiwała Koniec rozmowy, ale mogę się mylić.

W każdym razie http://javalangblog.blogspot.co.uk/2010/04/flush-mode-conversation.html zdaje się sugerować rozwiązanie

nadzieję, że pomaga.

EDIT: Można skonfigurować tryb płukania za rozmowę przy użyciu języka XML

<begin-conversation join="true" flush-mode="COMMIT" /> 

i stosując adnotacje

@Begin(flushMode=COMMIT) 

jednak pamiętać, że rozmowa może @end przy czym nie jest wyraźnie określona. Jeśli użytkownik jest w trakcie rozmowy, wprowadził zmiany w elementach, a następnie porzucił rozmowę, zostanie automatycznie zamknięty po upływie limitu czasu. Jeśli dobrze pamiętam, spowoduje to, że wszelkie zmiany zostaną wprowadzone w powyższej sprawie.

Odniesienia:

http://docs.jboss.org/seam/3/persistence/3.0.0.Alpha1/reference/en-US/html_single/#d0e249 http://docs.jboss.org/seam/3/latest/api/org/jboss/seam/persistence/FlushModeType.html

Powiązane problemy