Estou usando JSF2, JPA2 (Hibernate), e SQL Server 2008 e tenho com um problema para salvar uma entidade com uma lista de outras entidades no banco de dados após remover um item desta lista. Ao salvar a entidade com a lista, a entidade é atualizada e os novos itens da lista são incluídos ao banco de dados, mas os itens removidos desta lista não são excluídos do banco de dados.
As entidades:
[code]@Entity
@Table(name = “tbProposta”)
@NamedQueries({@NamedQuery(name = “proposta.getAll”, query = “select p from Proposta p”)})
public class Proposta implements PersistentEntity {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "cdProposta")
private Long id;
// ...
@OneToMany(cascade = CascadeType.ALL, mappedBy = "proposta")
@LazyCollection(LazyCollectionOption.FALSE)
private List<Posicionamento> posicionamentos;
public List<Posicionamento> getPosicionamentos() {
return posicionamentos;
}
public void setPosicionamentos(List<Posicionamento> posicionamentos) {
this.posicionamentos = posicionamentos;
}
public boolean addPosicionamento(Posicionamento posicionamento) {
if (posicionamentos == null) {
posicionamentos = new ArrayList<Posicionamento>();
}
if (posicionamentos.add(posicionamento)) {
if (posicionamento != null) {
posicionamento.setProposta(this);
}
return true;
}
return false;
}
public boolean removePosicionamento(Posicionamento posicionamento) {
if (posicionamentos != null) {
if (posicionamentos.remove(posicionamento)) {
if (posicionamento != null) {
posicionamento.setProposta(null);
}
return true;
}
}
return false;
}
[/code]
Posicionamento:
@Entity
@Table(name = "tbPosicionamento")
public class Posicionamento implements Comparable<Posicionamento>, Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cdPosicionamento")
private Long id;
@Column(name = "dsObservacaoPMO")
private String observacao;
@Column(name = "dtPosicionamento")
@Temporal(TemporalType.DATE)
private Date data;
@ManyToOne
@JoinColumn(name = "cdAvaliacao")
private Avaliacao avaliacao;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "cdProposta")
private Proposta proposta;
public Posicionamento() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getObservacao() {
return observacao;
}
public void setObservacao(String observacao) {
this.observacao = observacao;
}
public Date getData() {
return data;
}
public void setData(Date data) {
this.data = data;
}
public Avaliacao getAvaliacao() {
return avaliacao;
}
public void setAvaliacao(Avaliacao avaliacao) {
this.avaliacao = avaliacao;
if (avaliacao != null && avaliacao.getPosicionamentos() != null && !avaliacao.getPosicionamentos().contains(this)) {
avaliacao.addPosicionamento(this);
}
}
public Proposta getProposta() {
return proposta;
}
public void setProposta(Proposta proposta) {
this.proposta = proposta;
if (proposta != null && proposta.getPosicionamentos() != null && !proposta.getPosicionamentos().contains(this)) {
proposta.addPosicionamento(this);
}
}
@Override
public int hashCode() {
final int prime = 7;
int result = 11;
result = prime * result + ((data == null) ? 0 : data.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Posicionamento other = (Posicionamento) obj;
if (data == null) {
if (other.data != null) {
return false;
}
} else if (!data.equals(other.data)) {
return false;
}
if (id == null) {
if (other.id != null) {
return false;
}
} else if (!id.equals(other.id)) {
return false;
}
return true;
}
@Override
public String toString() {
return "Posicionamento [id=" + id + ", observacao=" + observacao + ", data=" + data + "]";
}
@Override
public int compareTo(Posicionamento other) {
return data != null ? data.compareTo(other.data) : -1;
}
O managedbean:
public abstract class AbstractManager {
public EntityManagerFactory emf;
public AbstractManager() {
emf = Persistence.createEntityManagerFactory("pmo");
}
protected final <T> T doInTransaction(PersistenceAction<T> action) throws ManagerException {
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
T result = action.execute(em);
em.getTransaction().commit();
return result;
} catch (Exception e) {
try {
em.getTransaction().rollback();
} catch (Exception ex) {
Logger.getLogger(AbstractManager.class.getName()).log(Level.SEVERE, null, ex);
}
throw new ManagerException(e);
} finally {
em.close();
}
}
protected final void doInTransaction(PersistenceActionWithoutResult action) throws ManagerException {
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
action.execute(em);
em.getTransaction().commit();
} catch (Exception e) {
try {
em.getTransaction().rollback();
} catch (Exception ex) {
Logger.getLogger(AbstractManager.class.getName()).log(Level.SEVERE, null, ex);
}
throw new ManagerException(e);
} finally {
em.close();
}
}
protected static interface PersistenceAction<T> {
T execute(EntityManager em);
}
protected static interface PersistenceActionWithoutResult {
void execute(EntityManager em);
}
protected void addMessage(String message) {
addMessage(null, message, FacesMessage.SEVERITY_INFO);
}
protected void addMessage(String componentId, String message) {
addMessage(componentId, message, FacesMessage.SEVERITY_INFO);
}
protected void addMessage(String message, Severity severity) {
addMessage(null, message, severity);
}
protected void addMessage(String componentId, String message, Severity severity) {
FacesContext.getCurrentInstance().addMessage(componentId, new FacesMessage(severity, message, message));
}
protected String getMessageForKey(String key) {
FacesContext fc = FacesContext.getCurrentInstance();
ResourceBundle rb = fc.getApplication().getResourceBundle(fc, "i18n");
return rb.getString(key);
}
protected FacesMessage getFacesMessageForKey(String key) {
return new FacesMessage(getMessageForKey(key));
}
protected Logger getLogger(Class<?> clazz) {
if (clazz == null) {
throw new IllegalArgumentException("Class for logger is required.");
}
return Logger.getLogger(clazz.getName());
}
protected void publishEvent(Class<? extends SystemEvent> eventClass, Object source) {
if (source != null) {
FacesContext fc = FacesContext.getCurrentInstance();
fc.getApplication().publishEvent(fc, eventClass, source);
}
}
protected void subscribeToEvent(Class<? extends SystemEvent> eventClass, SystemEventListener listener) {
FacesContext.getCurrentInstance().getApplication().subscribeToEvent(eventClass, listener);
}
protected void unsubscribeFromEvent(Class<? extends SystemEvent> eventClass, SystemEventListener listener) {
FacesContext.getCurrentInstance().getApplication().unsubscribeFromEvent(eventClass, listener);
}
@ManagedBean
@SessionScoped
public class PropostaManager extends AbstractManager implements Serializable {
private static final long serialVersionUID = 1L;
private Posicionamento posicionamento;
private DataModel<Posicionamento> posicionamentos;
private List<Posicionamento> posicionamentosList;
public Posicionamento getPosicionamento() {
return posicionamento;
}
public void setPosicionamento(Posicionamento posicionamento) {
this.posicionamento = posicionamento;
}
public DataModel<Posicionamento> getPosicionamentos() {
return posicionamentos;
}
public void setPosicionamentos(DataModel<Posicionamento> posicionamentos) {
this.posicionamentos = posicionamentos;
}
public List<Posicionamento> getPosicionamentosList() {
return posicionamentosList;
}
public void addPosicionamento(ActionEvent e) {
if (proposta != null) {
if (proposta.addPosicionamento(posicionamento)) {
posicionamentosList.add(posicionamento);
}
}
posicionamento = proposta.getUltimoPosicionamento();
novoPosicionamento = false;
}
public void removePosicionamento(ActionEvent e) {
if (proposta != null) {
posicionamento = posicionamentos.getRowData();
if (proposta.removePosicionamento(posicionamento)) {
posicionamentosList.remove(posicionamento);
}
}
proposta.getUltimoPosicionamento();
novoPosicionamento = false;
}
Método save:
[code]public String save() {
if (proposta != null) {
try {
Proposta merged = doInTransaction(new PersistenceAction() {
public Proposta execute(EntityManager em) {
Projeto projeto = proposta.getProjeto();
if (proposta.isNew()) {
Query q = em.createNamedQuery("projeto.getLast");
Long id = ((Projeto) q.getSingleResult()).getId() + 1;
projeto.setId(id);
em.persist(projeto);
// proposta.setPosicionamentos(posicionamentosList);
proposta.setId(id);
em.persist(proposta);
} else if (!em.contains(proposta)) {
em.merge(projeto);
return em.merge(proposta);
}
return proposta;
}
});
if (!proposta.equals(merged)) {
proposta = merged;
int i = propostasList.indexOf(proposta);
if (i != -1) {
propostasList.set(i, merged);
}
}
if (!propostasList.contains(merged)) {
propostasList.add(merged);
}
getLogger(getClass()).log(Level.INFO, proposta + " has been saved");
addMessage("Proposta salva", FacesMessage.SEVERITY_INFO);
} catch (Exception e) {
getLogger(getClass()).log(Level.SEVERE, "Error on try to save Proposta: " + proposta, e);
addMessage("Erro ao salvar a Proposta", FacesMessage.SEVERITY_ERROR);
return null;
}
}
initialize();
return "list";
}
[/code]
E a página:
[code] <rich:tab header=“Posicionamento”>
<rich:panel rendered="#{not propostaManager.novoPosicionamento}">
<h:outputLabel for=“ultimoObservacao” value=“Observação” />
<h:inputText id=“ultimoObservacao” value="#{propostaManager.proposta.ultimoPosicionamento.observacao}" />
<h:outputLabel for="ultimoData" value="Data" /><br />
<rich:calendar datePattern="dd/MM/yyyy" id="ultimoData" value="#{propostaManager.proposta.ultimoPosicionamento.data}" /><br />
<h:outputLabel for="ultimoAvaliacao" value="Avaliação" /><br />
<h:selectOneMenu converter="avaliacaoConverter" id="ultimoAvaliacao" value="#{propostaManager.proposta.ultimoPosicionamento.avaliacao}">
<f:selectItem itemLabel="Selecione uma avaliação" />
<f:selectItems itemLabel="#{avaliacao.nome}" itemValue="#{avaliacao}" value="#{avaliacaoManager.avaliacoes}" var="avaliacao" />
</h:selectOneMenu><br />
<h:commandButton actionListener="#{propostaManager.novoPosicionamento}" value="Novo"/>
</rich:panel>
<rich:panel rendered="#{propostaManager.novoPosicionamento}">
<h:outputLabel for="observacao" value="Observação" /><br />
<h:inputText id="observacao" value="#{propostaManager.posicionamento.observacao}" /><br />
<h:outputLabel for="data" value="Data" /><br />
<rich:calendar datePattern="dd/MM/yyyy" id="data" value="#{propostaManager.posicionamento.data}" /><br />
<h:outputLabel for="avaliacao" value="Avaliação" /><br />
<h:selectOneMenu converter="avaliacaoConverter" id="avaliacao" value="#{propostaManager.posicionamento.avaliacao}">
<f:selectItem itemLabel="Selecione uma avaliação" />
<f:selectItems itemLabel="#{avaliacao.nome}" itemValue="#{avaliacao}" value="#{avaliacaoManager.avaliacoes}" var="avaliacao" />
</h:selectOneMenu><br />
<h:commandButton actionListener="#{propostaManager.addPosicionamento}" value="ADICIONAR"/>
</rich:panel>
<rich:dataTable value="#{propostaManager.posicionamentos}" var="posicionamento">
<rich:column>
<f:facet name="header">
<h:outputText value="Observação" />
</f:facet>
<h:outputText value="#{posicionamento.observacao}" />
</rich:column>
<rich:column>
<f:facet name="header">
<h:outputText value="Data" />
</f:facet>
<h:outputText value="#{posicionamento.data}">
<f:convertDateTime pattern="dd/MM/yyyy" />
</h:outputText>
</rich:column>
<rich:column>
<f:facet name="header">
<h:outputText value="Avaliação" />
</f:facet>
<h:outputText value="#{posicionamento.avaliacao.nome}" />
</rich:column>
</rich:dataTable>
</rich:tab>
</rich:tabPanel>
[/code]
Alguém sabe o que posso fazer para solucionar o problema?
Obrigado.