Galera, estou tentando salvar uma entidade com relacionamento ManyToMany com atributos…
Estou recebendo esta bendita exception…
Caused by: javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: pacote.Campo
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1360)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1288)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1294)
at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:877)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
at $Proxy31.merge(Unknown Source)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:345)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:334)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:319)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
... 61 more
Vamos aos mapeamentos…
Entidade que quero salvar:
@Table(name = "com_prospecto")
@Entity
public class Prospecto {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "data_cadastramento")
@Temporal(TemporalType.TIMESTAMP)
private Date cadastramento;
@ManyToMany
@JoinTable(name = "com_historico_acoes", joinColumns = @JoinColumn(name = "id_prospecto"), inverseJoinColumns = @JoinColumn(name = "id_acao"))
private List<Acao> acoes;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "prospecto")
private List<ProspectoCampo> prospectoCampos;
Entidade que quero que também seja salva:
@Table(name = "com_prospecto_campo")
@Entity
@IdClass(ProspectoCampoId.class)
public class ProspectoCampo {
@Id
@ManyToOne
@JoinColumn(name = "id_prospecto")
private Prospecto prospecto;
@Id
@ManyToOne
@JoinColumn(name = "id_campo")
private Campo campo;
private String valor;
Id da classe anterior:
public class ProspectoCampoId implements Serializable {
private static final long serialVersionUID = 1L;
private Integer prospecto;
private Integer campo;
OBS: este mapeamento foi produto da leitura do seguinte blog do jakefrog (H. Coelho)!
E estou tentando salvar (na verdade é editar, mas isto é indiferente pois o Spring Data faz um save or update):
public String editar(){
prospecto = prospectoService.buscarProspectoComAcoes(prospecto.getId()); //isto é por causa do lazy loading...
for(ProspectoHelper hp : ProspectoHelper.extrairDadoDoModelo(dynaFormModelUniao)){ //ignorem esta linha
prospecto.adicionarCampo(hp.getPropertyFilter().getCampo(), hp.getPropertyFilter().getValue()); //criei um metodo no modelo para adicionar o campo... ja vou mostrar
}
prospecto.adicionarAcao(acaoSelecionada);
try{
prospectoService.save(prospecto);
}catch(Exception e){
log.error("Erro ao editar Prospecto!", e);
messageUtil.sendErrorMessageToUser("global.error", "global.insert.error", e.getMessage());
return null;
}
return getRadarPath();
}
O método que criei no modelo:
public void adicionarCampo(Campo campo, Object value) {
ProspectoCampo encontrado = encontrarProspectoCampo(campo);
if(encontrado == null){
ProspectoCampo pc = new ProspectoCampo();
pc.setProspecto(this);
pc.setCampo(campo);
pc.setValor(value.toString());
}else{
encontrado.setValor(value.toString());
}
}