darlan_machado 25 de jul. de 2018
A forma como o JPA gerencia as entidades se baseia em manter uma referência a cada elemento, permitindo, então, identificar se este objeto é um novo objeto ou se é um objeto distinto.
Por alguma razão, o método clonarSemID mantém a referência do objeto em questão, apenas removendo seu ID. Coincidentemente, o ID é a PK do objeto, logo, não pode ser nula quando um objeto já está gerenciado pelo JPA.
Christopherson_Carva 25 de jul. de 2018
Como faço para copiar os atributos do objeto e persistir como um novo então? Estou com uma aplicação que depende desta tarefa…
darlan_machado 25 de jul. de 2018
Por acaso o tipo do atributo id é um tipo primitivo?
Se for, dá uma olhada nisso
Christopherson_Carva 25 de jul. de 2018
Acredito que meu mapeamento está correto.
Vou tentar outras coisas aqui.
@Entity
@Table ( name = "Projeto" )
@TableModel
public class Projeto implements Entidade < Projeto > {
@Id
@GeneratedValue ( strategy = GenerationType . AUTO )
private Integer id ;
@Column ( colName = "Nome" , colPosition = 0 )
private String nome ;
private String autor ;
@Column ( colName = "Data" , colPosition = 1 )
private String data ;
private String descricao ;
@OneToMany ( cascade = CascadeType . ALL )
private List < Fonte > fontes ;
public Projeto () {
fontes = new ArrayList <> ();
}
public void setAutor ( String autor ) {
this . autor = autor ;
}
public void setData ( String data ) {
this . data = data ;
}
public void setDescricao ( String descricao ) {
this . descricao = descricao ;
}
public void setFontes ( List < Fonte > fontes ) {
this . fontes = fontes ;
this . fontes . clear ();
this . fontes . addAll ( fontes );
}
public void setId ( Integer id ) {
this . id = id ;
}
public String getNome () {
return nome ;
}
public void setNome ( String nome ) {
this . nome = nome ;
}
public String getAutor () {
return autor ;
}
public String getData () {
return data ;
}
public String getDescricao () {
return descricao ;
}
public List < Fonte > getFontes () {
return fontes ;
}
@Override
public Projeto clonarSemID () {
Projeto p = copiar ();
p . setId ( null );
return this ;
}
@Override
public Projeto copiar () {
Projeto p = new Projeto ();
p . setId ( id );
p . setNome ( nome );
p . setAutor ( autor );
p . setData ( data );
p . setDescricao ( descricao );
for ( Fonte f : fontes ) {
p . fontes . add ( f );
}
return this ;
}
@Override
public boolean equals ( Object obj ) {
if ( this == obj )
return true ;
if ( obj == null )
return false ;
if ( getClass () != obj . getClass ())
return false ;
final Projeto other = ( Projeto ) obj ;
if ( id == null ) {
if ( other . id != null )
return false ;
} else if ( ! id . equals ( other . id ))
return false ;
return true ;
}
@Override
public Integer getId () {
return id ;
}
@Override
public int hashCode () {
final int prime = 31 ;
int result = 1 ;
result = prime * result + (( id == null ) ? 0 : id . hashCode ());
return result ;
}
@Override
public String toString () {
return nome ;
}
@Override
public void apagar () {
id = null ;
nome = "" ;
autor = "" ;
descricao = "" ;
fontes . clear ();
}
}
Christopherson_Carva 25 de jul. de 2018
Resolvido.
É necessário sempre criar uma nova instância.
public class testeconexao {
public static void main ( String [] args ) {
EntityManagerFactory emf = Persistence . createEntityManagerFactory ( "EletricaPU" );
EntityManager em = emf . createEntityManager ();
Projeto projeto = new Projeto ();
projeto . setNome ( "Chris" );
projeto . setAutor ( "projeto" );
projeto . setDescricao ( "teste" );
projeto . setData ( DataUtil . Atual ());
em . getTransaction (). begin ();
em . persist ( projeto );
em . getTransaction (). commit ();
Projeto projeto2 = new Projeto ();
projeto2 . setNome ( projeto . getNome ());
projeto2 . setAutor ( projeto . getAutor ());
projeto2 . setDescricao ( projeto . getDescricao ());
projeto2 . setData ( projeto . getData ());
em . getTransaction (). begin ();
em . persist ( projeto2 );
em . getTransaction (). commit ();
}
}
darlan_machado 25 de jul. de 2018
Isso já estava sendo feito.
Christopherson_Carva 25 de jul. de 2018
Acho que o Hibernate não entende como objeto novo fazendo dessa forma. Realmente não entendo. Ele copia a referencia do objeto anterior mesmo criando um novo dessa forma.
Usando o CloneSemID(), e comparando Projeto1 e Projeto2, o equals() retorna True!!!
@Override
public boolean equals ( Object obj ) {
if ( this == obj )
return true ;
if ( obj == null )
return false ;
if ( getClass () != obj . getClass ())
return false ;
final Projeto other = ( Projeto ) obj ;
if ( id == null ) {
if ( other . id != null )
return false ;
} else if ( ! id . equals ( other . id ))
return false ;
return true ;
}
public class testeconexao {
public static void main ( String [] args ) {
EntityManagerFactory emf = Persistence . createEntityManagerFactory ( "EletricaPU" );
EntityManager em = emf . createEntityManager ();
Projeto projeto = new Projeto ();
projeto . setNome ( "Chris" );
projeto . setAutor ( "projeto" );
projeto . setDescricao ( "teste" );
projeto . setData ( DataUtil . Atual ());
em . getTransaction (). begin ();
em . persist ( projeto );
em . getTransaction (). commit ();
Projeto projeto2 = projeto . clonarSemID ();
System . out . println ( projeto2 . equals ( projeto )); //true
em . getTransaction (). begin ();
em . persist ( projeto2 );
em . getTransaction (). commit ();
}
}
darlan_machado 25 de jul. de 2018
Nem olhei o return.
Mas, é exatamente isso!
Christopherson_Carva 25 de jul. de 2018
staroski 27 de jul. de 2018
Não, não, não!
A instrução new sempre aloca uma nova região de memória, ou seja, é um novo objeto!
O problema é esse:
@Override
public Projeto copiar () {
Projeto p = new Projeto (); // Criou o objeto p
p . setId ( id );
p . setNome ( nome );
p . setAutor ( autor );
p . setData ( data );
p . setDescricao ( descricao );
for ( Fonte f : fontes ) {
p . fontes . add ( f );
}
return this ; // mas retornou o objeto this
}