Ho un'applicazione sandbox Seam 3 che utilizza JBoss 7, Hibernate come implementazione JPA predefinita e come JSF come front-end web.JPA/Hibernate non emette alcun UPDATE sul commit nell'ambiente EJB/Seam
Ho il problema, che SQL UPDATE è ingerito di default.
mio EJB stateful portata conversazione mantiene un esteso con scope EntityManager e una sola entità, transazioni gestite container (richiede nuove)
- L'EntityManager viene iniettato
- L'EJB utilizza il EM per caricare l'Entity e mantiene in un campo
- applicazione JSF accede al EJB e la sua entità, cambia un campo stringa
- calles un'applicazione JSF metodo "Save" in EJB
- in save() Controllo, se il campo Entities è stato modificato -> è stato modificato correttamente
- Non faccio altro, il container esegue la transazione dopo che save() è terminato.
- Problema: non viene eseguito alcun aggiornamento SQL sul DB.
Se estendo save() da:
a) entityManager.contains (entità) l'aggiornamento viene eseguito come previsto (risultato è "true")
O
b) entityManager.persist (entità) UPDATE viene eseguito come previsto
Q: Per quanto ne so, le specifiche non sono né a) né b), poiché l'Entità rimane gestita durante l'intero processo. Non capisco, perché a) ha un effetto sul risparmio. Posso immaginare il b) ha un effetto sul salvataggio, ma non dovrebbe essere richiesto, dovrebbe?
Qualsiasi spiegazione è la benvenuta.
Ecco il mio 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";
}
}
ho scoperto entityManager.flush() risolve anche il problema. Ma non capisco perché questo sembra essere richiesto. Dalla specifica JPA: "Quando la transazione JTA viene eseguita, il provider deve scaricare lo stato di tutte le entità modificate nel database ". – user1187037
forse da qualche parte la modalità Flush della sessione di ibernazione è impostata su nessuna? – Firo