Hibernate: update/merge somente em alguns campos.

1,250 views
Skip to first unread message

jopss...@hotmail.com

unread,
Feb 3, 2009, 1:05:29 PM2/3/09
to JUG-MS
Olá.... estou com uma dúvida sobre Hibernate que não consegui resolver
somente com pesquisas. Talvez a experiencia de vocês possam me dar uma
luz......

Basicamente tenho uma tabela no banco de dados e um objeto mapeado
para ele.

Quero alterar uma entrada nessa tabela, entao crio um objeto, seto seu
id e 2 campo que quero alterar, e o hibernate "nula" todos os outros
campos daquela entrada!

Fazer o "load" ou um "select" para tal objeto é um custo muito
desnecessário, pois tem vários campos, e a ação é efetuada a todo o
momento. Existe como alterar somente os campos que eu quero sem
precisar fazer um "UPDATE" na mão?

Dei uma pesquisada e nao achei.

Além do mais, ocasiona erro ao fazer UPDATE por HQL. Pode ser problema
do driver SqlServer. No SQL gerado ele insere uma virgula logo após o
nome da tabela (classe), e me retorna erro.

Da HQL:
# UPDATE Objeto obj SET obj.valor = :valor WHERE obj.id = :idObjeto

Me retorna a SQL e o erro:
# update TB_TABELA, set TB_VALOR=? where TB_ID=?

# SQL Error: 102, SQLState: S0001
# Incorrect syntax near ','.

Alguem poderia saber porque? Ou uma solução?
jopss

Postei a mesma dúvida no GUJ: http://www.guj.com.br/posts/list/116936.java#632763

Leonides Fernando

unread,
Feb 3, 2009, 1:22:30 PM2/3/09
to jug...@googlegroups.com

  Olá jopss,

talvez o que voce precisa entender é a estrutura do Hibernate e o clico de vida dado por ele a um objeto. Espero que esses posts possam te ajudar:
http://www.devmedia.com.br/articles/viewcomp.asp?comp=4742
http://blog.caelum.com.br/2006/11/23/entidades-managed-transient-e-detached-no-hibernate-e-jpa/

mas quando voce fala ... "Fazer o "load" ou um "select" para tal objeto é um custo muito
desnecessário, pois tem vários campos
..." será que  normalizá-la não resolve esse problema ? Assim bastaria um load no objeto e setar os atributos desejados e seu registro seria alterado.

[]'s





--
Leonides Fernando

Gilliard Cordeiro

unread,
Feb 3, 2009, 1:39:01 PM2/3/09
to jug...@googlegroups.com
Se eu compreendi bem, o que voce quer usar é o dynamic-update e/ou dynamic-insert. Se voce tiver usando anotações, esses atributos estão disponívels na anotação @org.hibernate.annotations.Entity, com os nomes de dynamicUpdate e dynamicInsert respectivamente. O valor default é false, e mudando pra true deveria começar a fazer o que você quer. mas olha certinho a documentação pois deve ter algumas restrições ou formas "corretas" de usar pra fazer funcionar.

2009/2/3 Leonides Fernando <lf....@gmail.com>

Gilliard Cordeiro

unread,
Feb 3, 2009, 1:45:35 PM2/3/09
to jug...@googlegroups.com
Ah, outra coisa que voce pode tentar fazer junto com o dynamicUpdate, pra ver se funciona, é em fez de carregar o objeto, voce apenas dar um getReference (JPA) ou um get (Hibernate), pois esses métodos não carregam o objeto do banco, apenas criam uma instancia gerenciada com a chave que vc passou.

2009/2/3 Gilliard Cordeiro <gscor...@gmail.com>

jopss...@hotmail.com

unread,
Feb 3, 2009, 1:51:15 PM2/3/09
to JUG-MS
opa!! vlw ae!! já vou testar aqui....

Só uma duvida: no caso, eu poderia criar uma instancia e usar merge?

Gilliard Cordeiro

unread,
Feb 3, 2009, 1:57:50 PM2/3/09
to jug...@googlegroups.com
tem que testar certinho. talvez o objeto precise estar gerenciado, ou pelo menos ter sido criado pelo hibernate para ter algum tipo de estrutura interna que permita o hibernate saber quais campos foram alterados... pois criando na mão, acredito que a única forma do hibernate saber se o objeto foi mudado ou não seja fazendo um select, coisa que pelo jeito você não gostaria de fazer.

jopss...@hotmail.com

unread,
Feb 3, 2009, 2:06:06 PM2/3/09
to JUG-MS
opa!!! seguinte:

criando um objeto na mão e setando com "merge" não funciona!
usando "session.get" para pegar o objeto e usando "update" FUNCIONOU!!

Agora vem outra dúvida: alguem já obteve algum problema usando
"dynamicUpdate" ????
E estou usando XML e não Annotations....

Verifiquei na net que tem vários post sobre problemas com este, mas
não cheguei a ver todos os erros.....

E outra: Perguntei sobre o "merge" com objeto novo, pq o este não
serve para pegar objetos "sem referencia" e deixá-los managed? Mas não
funfo!

jopss

jopss...@hotmail.com

unread,
Feb 3, 2009, 2:21:32 PM2/3/09
to JUG-MS
Opa!! não funfo não!! rs....

no caso nao deu erros, e pensei que estava como queria, mas verifiquei
que meu objeto retornado pelo "get" está todo populado!! Os atributos,
referencias, listas, está tudo lá.......

agora não sei mais...

jopss

Castilho

unread,
Feb 3, 2009, 2:29:07 PM2/3/09
to jug...@googlegroups.com
jopss,
alguns pontos importantes:

- O Hibernate possui 2 níveis de cache. Entao, se vc faz multiplos load ou get, nao necessariamente o hibernate irá fazer multiplos SELECTs. Por isso, nao preocupe-se tanto em querer fazer atualizaçoes sem carregar o objeto antes.

- Eu acho que o dynamic-update serve para avisar ao hibernate que apenas os campos alterados devem ser atualizados. Mas, para que ele saiba quais campos foram alterados, ele precisa saber primeiro o valor que existia naqueles campos (ou seja, vc tem que dar um load ou get e trazer o objeto para a memória)

- No Hibernate 2, para gerenciar um objeto "destacado" vc deve usar o método lock, usando lock-mode = NONE (ou algo assim). No Hibernate 3, que é uma implementação JPA, acho que a especificação não define uma forma de fazer isso. 

- O metodo merge serve para atualizar no banco de dados alteracoes que foram feitas em um objeto que já está "destacado". Se o objeto estiver gerenciado pelo Hibernate, o merge nao precisa ser feito pois o hibernate já atualizará esse objeto qdo achar conveniente ou qdo a  transação a qual ele pertence for finalizada.

Sugestao: Faça o get do objeto antes de altera-lo. Se esse objeto carrega uma arvore grande de objetos, utilize lazy-load para evitar a carga ou entao pense na possibilidade de refinar seu modelo de classes, para que poucos dados sejam enviados para a memória.

[]s
Castilho

jopss...@hotmail.com

unread,
Feb 3, 2009, 2:37:06 PM2/3/09
to JUG-MS
Pois é..... meu problema é que não posso, atualmente, utilizar "lazy-
load" pois isso matará alguns codigos legados que tem no projeto, e
além, os dados retornados é grande, e ainda acessados a um timer. E
por enquanto não temos cache 2 do hiber tbm.

Bom, não vejo solução a não ser fazer UPDATE na mão mesmo...
Alguem tem mais alguma dica?

vlw a todos!
jopss

Gilliard Cordeiro

unread,
Feb 3, 2009, 2:45:12 PM2/3/09
to jug...@googlegroups.com
é complicado mesmo hein....
as observações do Castilho foram completas, nao tenho o que falar.

agora só falando em relação ao get que carregou, talvez o "gatilho" para fazer o load nao esteja só no get, mas no set também. Pois o get e o getReference (acho que os nomes são esses) não carregam o objeto do banco.

e o merge eu já testei em objetos novos e funciona igual ao caso do detached (nessa caso vai ter um insert). no final do merge sempre vai ter um objeto managed, seja o objeto passado um detached, new ou mesmo um managed. Mas não sei dizer o que a especificação diz a respeito disso. Não que vá acontecer do hibernate contrariar a especificação, mas as vezes não está muito bem definido e ele resolve do jeito dele. Mas como no caso voce está usando hibernate mesmo, e nao jpa, nao tem problema.


Reply all
Reply to author
Forward
0 new messages