Pessoal, to precisando fazer algo bem simples, mas do jeito que fiz não deu certo.
Na minha aplicação, quando o usuário clicar editar, na verdade não quero editar e sim salvar um novo registro.
Ex: tenho um cadastro de Ponto e outro de PontoConfig (um pra muitos), quando alterar um PontoConfig eu mantenho aquelas informações no banco e salvo uma nova (já com as alterações), tenho que fazer isso pra manter um histórico de alterações.
O que fiz? Instanciei um novo objeto e setei nele as informações do outro objeto, ele cria um novo registro, mas o antigo também está sendo alterado, segue o código:
@Begin
public String configPoint() {
if(pointConfig.getPointConfigId() != null) {
pointConfigEdit = new PointConfig(); // instancio um novo objeto (pointConfigEdit) para guardar as informações da alteração
entityManager.refresh(pointConfig); // recupero o objeto pointConfig
}
return "configPoint";
}
@End
public String savePointConfig() {
if (pointConfig.getPointConfigId() != null) {
/* seto em pointConfigEdit as informações de pointConfig */
pointConfigEdit.setClient(pointConfig.getClient());
pointConfigEdit.setEquipmentInstallation(pointConfig.getEquipmentInstallation());
pointConfigEdit.setFormula(pointConfig.getFormula());
pointConfigEdit.setPoint(point);
pointConfigEdit.setRegister(pointConfig.getRegister());
pointConfigEdit.setSensor(pointConfig.getSensor());
pointConfigEdit.setTeam(pointConfig.getTeam());
pointConfigEdit.setConfigAlert(pointConfig.getConfigAlert());
entityManager.persist(pointConfigEdit); // persisto apenas pointConfigEdit, mas no banco tá alterando também o pointConfig!!!
}
listPoints();
return "savePointConfig";
}
Porque tá dando um merge no pointConfig?
O que tenho que fazer para isso dar certo?
Obrigado!
Provavelmente por causa do seu mapeamento.
PointConfigEdit está como “pai” na relação. Assim quando é editado salva as informações do pointConfig
[quote=Graciano]Provavelmente por causa do seu mapeamento.
PointConfigEdit está como “pai” na relação. Assim quando é editado salva as informações do pointConfig[/quote]
E aí Graciano, na verdade PointConfigEdit é uma nova instancia de PointConfig.
Eu recupero pointConfig através do método refresh, instancio um novo objeto (pointConfigEdit), seto nesse novo objeto as infos de pointConfig e dou um persist no novo objeto.
Provavelmente não seja a maneira correta a se fazer, sabe como eu poderia fazer isso (criar novo objeto ao invés de editar)?
Obrigado
[quote=samerjamal]Pessoal, to precisando fazer algo bem simples, mas do jeito que fiz não deu certo.
Na minha aplicação, quando o usuário clicar editar, na verdade não quero editar e sim salvar um novo registro.
Ex: tenho um cadastro de Ponto e outro de PontoConfig (um pra muitos), quando alterar um PontoConfig eu mantenho aquelas informações no banco e salvo uma nova (já com as alterações), tenho que fazer isso pra manter um histórico de alterações.
![/quote]
Não mantenha o historico na propria tabela. Crie uma tabela de historico. Manipule apenas o mais recente.
[quote=sergiotaborda][quote=samerjamal]Pessoal, to precisando fazer algo bem simples, mas do jeito que fiz não deu certo.
Na minha aplicação, quando o usuário clicar editar, na verdade não quero editar e sim salvar um novo registro.
Ex: tenho um cadastro de Ponto e outro de PontoConfig (um pra muitos), quando alterar um PontoConfig eu mantenho aquelas informações no banco e salvo uma nova (já com as alterações), tenho que fazer isso pra manter um histórico de alterações.
![/quote]
Não mantenha o historico na propria tabela. Crie uma tabela de historico. Manipule apenas o mais recente.[/quote]
Mas essa não é uma decisão minha, é uma especificação 
será que o método clone() resolveria meu problema?
Pessoal, tentei com o método clone(), pelo debug vi que ele tá copiando o objeto em outra instância realmente, só que deu o seguinte erro:
javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: org.domain.infralogjava.entity.PointConfig
Segue o código:
@Begin
public String configPoint() {
if(pointConfig.getPointConfigId() != null) {
entityManager.refresh(pointConfig);
}
return "configPoint";
}
@End
public String savePointConfig() throws CloneNotSupportedException {
if (pointConfig.getPointConfigId() != null) {
pointConfigEdit = (PointConfig) pointConfig.clone();
entityManager.persist(pointConfigEdit);
}
listPoints();
return "savePointConfig";
}
Alguém tem idéia do porque isso ocorre?
sete o campo pointConfigId para null.
Quando o campo @Id do Hibernate não for null ele vai acreditar que o objeto não é novo.
Felagund, eu fiz isso e não deu também, setei antes de clonar, segue o erro:
org.hibernate.HibernateException: identifier of an instance of org.domain.infralogjava.entity.PointConfig was altered from 27 to null
Código:
@Begin
public String configPoint() {
if(pointConfig.getPointConfigId() != null) {
entityManager.refresh(pointConfig);
}
return "configPoint";
}
@End
public String savePointConfig() throws CloneNotSupportedException {
if (pointConfig.getPointConfigId() != null) {
pointConfig.setPointConfigId(null);
pointConfigEdit = (PointConfig) pointConfig.clone();
entityManager.persist(pointConfigEdit);
}
listPoints();
return "savePointConfig";
}
Vi no debug que está copiando corretamente, e o pointConfigId do pointConfigEdit é criado como null, mas o clone não persiste!!
Ta, então assim cara, esse problema ocorre pq a classe da no EntityManager já, ele acredita que vc esta modificando uma classe ja salva, e ela ja esta no contexto do EM.
Qual a utilidade do refresh na entidade? existem mesmo a necessidde de sincronizar a entidade com o banco antes de salvar?
Experimente remover esse refresh e executar o save.
att
[quote=Felagund]Ta, então assim cara, esse problema ocorre pq a classe da no EntityManager já, ele acredita que vc esta modificando uma classe ja salva, e ela ja esta no contexto do EM.
Qual a utilidade do refresh na entidade? existem mesmo a necessidde de sincronizar a entidade com o banco antes de salvar?
Experimente remover esse refresh e executar o save.
att[/quote]
Então velho, eu tenho que dar refresh sim, pq é uma edição, preciso recuperar as informações.
Uma vez que as recupero, quero copiá-las para uma nova instancia e salvá-las, pois não quero dar update nas informações antigas (quero mante-las inalteradas) e sim salvar as alterações em um novo registro.
Não sei se conseguiu entender e nem sei se é a maneira correta de se fazer isso.
Abraços!
Pra historico, use o ENVERS do hibernate.
Mas, se realmente quer fazer isso na mao, de um clear no entitymanager e depois sete a PK para null/zero
[quote=Paulo Silveira]Pra historico, use o ENVERS do hibernate.
Mas, se realmente quer fazer isso na mao, de um clear no entitymanager e depois sete a PK para null/zero[/quote]
Valeu Paulo e todos que responderam, usando o clear() deu certo.
E usarei o Envers sim, mas para esse caso específico não posso, preciso fazer na unha mesmo.
Abraços!