@Entity
@Table(name="tabela")
@SequenceGenerator(name = "sequence", sequenceName = "sequence", allocationSize = 1)
public class Banco_Dados {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence")
private Long id;
private String campo A;
private String campo B;
private Integer campo C;
private Integer campo D;
private Integer campo E;
....
Em algum lugar da minha página faço um UPDATE setando apenas um atributo, por exemplo:
quando faço isso ele faz o Update deste campo, mas grava NULL para os outros que não foram setados!!! já tentei com Merge e UpdateOrSave, mas ambos ocorre o mesmo problema.
Como devo tratar isso ?? pra ele fazer o update dos campos setados e manter os valores dos campos que não foram setados no parâmetro ??
Bom dia.
Quando voce busca algum dado do BD atravez do Hibernate voce passa como parametro um identificador que creio eu ser o seu ID. Bem com isso quando voce carrega o dado objeto na sessao e atualiza este objeto mudando apenas um atributo voce nao precisa dar um comando save ou saveOrUpdate. O proprio objeto em cache atualiza automaticamente no banco ja que a transacao esta aberta.
Veja isso…
session = new HibernateUtil().getSession();
Transaction tx = session.beginTransaction();
Item item = new Item();
item = (Item)session.get(Item.class, 22L);
item.setDesconto(33.0);
tx.commit();
session.close();
Espero ter te ajudado e se acaso eu estiver errado, por favor me avisem… obrigado…
Ate mais.
Tentei fazer apenas dando commit mas não funcionou !!! Também tentei usar a anotação @org.hibernate.annotations.Entity(
optimisticLock = OptimisticLockType.ALL , dynamicUpdate = true) na minha Entidade, mas também não funcionou!!!
Acho melhor por meus métodos aqui:
DAO Genérico:
public void atualiza(T u){
this.session.merge(u);
}
Logic:
public void update(Entidade entidade){
this.daoFactory.beginTransaction();
this.daoFactory.getEntidadeDao().atualiza(entidade);
this.daoFactory.commit();
}
Só uma dúvida, se eu fizer um load depois eu não tenho que sair setando atributo por atributo ??? se sim, no caso da tabela ter 200 campos, fica meio complicado fazer isso !!! Como no meu caso, onde o VRaptor seta os atributos de acordo com os parametros passados, como no exemplo que citei do checkbox ??
public void update(Entidade entidade){
this.daoFactory.beginTransaction();
this.daoFactory.getEntidadeDao().atualiza(entidade);
this.daoFactory.commit();
}
public Entidade getEntidade(){
return entidade;
}
Bem, em todo caso como se encaixaria o load usando o código acima ??
Só complementando quadno você da um load ou get (le na doc que tem diferença) é o mesmo que você tivesse dado um select na tabela e carregado todas as propriedades do objeto.
acho que você deveria ler uns tutoriais de Hibernate (ou outro framework), para consolidar melhor algumas ideias
[quote=ddduran]Só complementando quadno você da um load ou get (le na doc que tem diferença) é o mesmo que você tivesse dado um select na tabela e carregado todas as propriedades do objeto.
acho que você deveria ler uns tutoriais de Hibernate (ou outro framework), para consolidar melhor algumas ideias[/quote]
Vou dar uma lida sim mais profunda na documentação, inclusive acabei de comprar um livro, mas não cheguei na parte de hibernate ainda !!
Mas enquanto isso, me ajude por favor…
Se eu fizer assim:
public void update(Entidade entidade){
entidade = this.daoFactory.getEntidadeDao().loadRegistro(entidade.getId_entidade());
this.daoFactory.beginTransaction();
this.daoFactory.getEntidadeDao().atualiza(entidade);
this.daoFactory.commit();
}
public Entidade getEntidade(){
return entidade;
}
Ele recupera o objeto no banco e ignora os novos valores passados por parametros !!! consequência: não persiste a alteração desejada !!
quando você ta dando o load você está realmente sobreponto suas informações com as que estão no banco.
vo tem que fazer assim
1 - o load não estaria dentro do seu metodo update mas sim no componente que chama o metodo update
2 - antes de atribuir os novos valores você da um load nesse objeto
3 - depois você muda os valores da sua entidade
4 - executa o metodo update
algo como isso
MinhaEntidade entidade = dao.loadRegistro(idInjetadoPeloVraptor);
entidade.setAtributoQueQueroAlterar(valorInjetadoPeloVraptor);
// e assim para todos os atributos que quero alterar
...
dao.update(entidade);
t.commit();
um conselho paralelo, evite dar o commit dentro do seu metodo update, por que isso impediria você usar transações efetivamente
Cara, desculpa vi agora que esse metodo update não é um metodo de DAO e sim o metodo que vai ser chamado pelo VRaptor, ne?
então ficaria assim:
public void update(Entidade entidade){
Entidade e = this.daoFactory.getEntidadeDao().loadRegistro(entidade.getId_entidade());
e.setAtributoQueQueroAlterar(entidade.getAtributoQueQueroAlterar());
// e assim vai
....
this.daoFactory.beginTransaction();
this.daoFactory.getEntidadeDao().atualiza(entidade);
this.daoFactory.commit();
}
public Entidade getEntidade(){
return entidade;
}
Por favor, um pouco de paciência comigo !!! rsrsrsrsrs
Então, dessa maneira que está seu código mostra justamente aquele problema que falei anteriormente, de ficar setanto atributo por atributo. Ai que pega, pois posso alterar 1 atributo como 200… isso é dinâmico !!!
E na verdade, o public void update é o componente, o método está no Dao Genérico, como postei anteriormente.
eu não me recordo de cabeça se um dos metodos do hibernater de atualização (merge, sabe, update, perisist) tem a caracteristicas de atualizar
ignorando campos nulos realmente nesse momento decepciono-me como desenvolvedor
mas vamos ver, no seu Entity, todos os campos dele não estão no seu formulario anterior?
vai lhe custar tanto assim à manutenção você estipular os campos que serão atualizados?
o seu “Entidade”, não contem o estado correto atual do objeto? você pode simplesmente persistilo.
uma ultima alternativa seria o seguinte, você ao inves de receber como parametro do metodo seu “Entidade”, coloque ele como um atributo do seu componente e deixe ele com escopo de sessão.
Se você está editando um certo elemento do seu banco de dados significa que em algum momento você já o carregou. (logo ele vai estar carregado na sua sessão)
logo quando o VRAPTOR for chamar esse seu metodo (update) ele vai alterar apenas os campos que você tem parametro na requisição
e você poderá persisti-lo.
Não sei se ficou claro esse ultimo, mas acho que seria uma boa solução
Analisando bem o causador desse problema é o VRaptor !!! veja, eu tenho no meu request apenas 1 atributo, que pertence a uma entidade com N atributos, o VRaptor seta NULL para todos os outros atributos que não estão no meu request, e como NULL é considerado um valor, o Hibernate compara que NULL <> valor antigo, então grava !!!
Um exemplo do que estou falando é o mentawai, lá se eu tenho uma Entidade com 100 atributos e em algum lugar do meu sistema eu tenho um FORM com apenas 10 desses 100 atributos ele altera apenas esses 10 sem eu ter que ficar recuperando o objeto da sessão e sair setando os 10 atributos para depois persistir.
Alguém conhece bem o VRaptor e sabe como resolver este problema ??