[RESOLVIDO] JPA - Obter chave gerada por Sequence em Trigger
29 respostas
P
paulohbmetal
Olá pessoal, blz?
Estou com um ‘probleminha’ aqui que está me enchendo… Tenho uma entidade ‘Pai’ e uma entidade ‘Filha’ (nomes fictícios) que possuem relacionamento 1 para N. A entidade Pai está mapeado para uma tabela no banco que possui uma Trigger (Before Insert - Oracle) que gera a chave primária automaticamente (buscando de uma sequence) … Porém, ao inserir um registro, a JPA não pega o ID gerado pela sequence na Trigger e sim um novo que ela mesma busca (fazendo select na sequence). O que resulta em um:
ORA-02291: restrição de integridade ... violada - chave mãe não localizada
ao inserir as entidades filhas. Ou seja, o registro inserido fica com um valor de ID e a entidade Pai fica com outro valor de ID.
Pode-se primeiro persistir o pai e depois setar os filhos e “merdiar” o pai novamente.
L
Laubstein_M_cio
Li novamente e agora entendi a sua dúvida…pensando rs…
P
paulohbmetal
É justamente isso que estou fazendo.
Paz e bem!
P
paulohbmetal
Ah tá. rsrsrs…
Paz e bem!
L
Laubstein_M_cio
humnn dexo ver, se você antes de persistir utilizar a sequence X que gera o nº 1, somente para que o provedor de persistencia não reclame da ausência do ID, na trigger ele ira gerar outro número para a chave com a sequence, terminando com o seu objeto pai após a persistencia com a sequence da trigger, se após isso você setar a List de filhos na pai e dar merge, a chave estrangeira da tabela pai na tabela de filhos não estara correta?
L
Laubstein_M_cio
ou o objeto pai após a persistencia ficou com um ID nº1 e não o da trigger?
Qual situação esta ocorrendo?
P
paulohbmetal
Pois é mas, para isso eu teria que fazer uma chamada a classe de persistência só para fazer merge. Quando mando persistir, meu objeto já está pronto (inclusive com os filhos preenchidos). Até poderia fazer um ‘cascade’ ao fazer o INSERT mas, ocorre o mesmo erro (já testei).
Paz e bem!
P
paulohbmetal
Laubstein:
ou o objeto pai após a persistencia ficou com um ID nº1 e não o da trigger?
Qual situação esta ocorrendo?
Isso, o objeto Pai está ficando com o primeiro ID e não o gerado pela Trigger.
Paz e bem!
L
Laubstein_M_cio
Entendi, não vejo outra saída cara, eu faria a persistencia do Pai, com o List de filhos nulo e depois os preencheria e realizaria mais uma chamada para o merge.
Vamos esperar se mais ninguém pode nos ajudar.
Abraço!
P
paulohbmetal
Laubstein:
Entendi, não vejo outra saída cara, eu faria a persistencia do Pai, com o List de filhos nulo e depois os preencheria e realizaria mais uma chamada para o merge.
Vamos esperar se mais ninguém pode nos ajudar.
Abraço!
É, eu não posso fazer isso pois essa entidade é resultado de um cálculo (que pode não dar certo) que gera esses filhos. Não faz sentido gravar antes de saber se está ok. Pelo menos pro meu caso. Mesmo assim, valeu d+ a ajuda! :thumbup:
Mais alguém?! :roll:
Paz e bem!
L
Laubstein_M_cio
Entendi, achei que ele ficava com o da trigger, ai realmente fud@@ de vez … rsrs
Uma vez que tentar recuperar novamente o objeto você não poderá contar com o valor atual da sequence, já que alguém pode estar a modificando, a não ser que você crie um mecanismo para poder recupera-la sem erros, bem isso é gambi rs.
L
Laubstein_M_cio
Mas até ai desacopla-los e depois acopla-los não é um problema e sim a sequence
L
lap_junior
Já que existe uma trigger que inclui o ID automaticamente na tabela, por que você não configura este ID como uma coluna de auto incremento, já testou isto?
Este comendo pode ser utilizado tanto para inserir quanto para saber qual o próximo ID.
Espero ter ajudado de alguma forma.
L
lap_junior
alexlima72:
É Oracle e o sequence já é auto incremento…
via SQL: (insert…minha_sequence.NEXTVAL).
Este comendo pode ser utilizado tanto para inserir quanto para saber qual o próximo ID.
Espero ter ajudado de alguma forma.
Acredito que todos aqui saibam disto, mas você leu qual é o motivo do problema? Que existe uma trigger que insere o ID antes do insert ser executado.
flw
L
Laubstein_M_cio
AUTO, deixará o provedor escolher a melhor estrategia para o banco de dados inferior, no caso se for o oracle provavelmente a escolha é SEQUENCE.
L
lap_junior
lap_junior:
Já que existe uma trigger que inclui o ID automaticamente na tabela, por que você não configura este ID como uma coluna de auto incremento, já testou isto?
Acabei copiando errado, não AUTO mas sim IDENTITY. Isso porque com esta trigger esta coluna funciona como se fosse autoincremento.
L
Laubstein_M_cio
Não lembro se Oracle suportam colunas de identidade… tem de testar.
L
Laubstein_M_cio
Acho que não, de qualquer forma acho que o problema continuaria.
P
paulohbmetal
lap_junior:
lap_junior:
Já que existe uma trigger que inclui o ID automaticamente na tabela, por que você não configura este ID como uma coluna de auto incremento, já testou isto?
Acabei copiando errado, não AUTO mas sim IDENTITY. Isso porque com esta trigger esta coluna funciona como se fosse autoincremento.
O Oracle não suporta colunas IDENTITY. Isso é usado no SQL Server e outros…
Paz e bem!
P
paulohbmetal
anyone? :roll:
L
Laubstein_M_cio
Putz ainda nada T_T, tentou outras alternativas cara? Posta aí para discutirmos.
L
Laubstein_M_cio
Nessa mesma tabela, você grava um campo TimeStamp?
P
peerless
questão complicada, considere estender o hibernate e criar sua própria estratégia de geração de sequence.
L
Laubstein_M_cio
O.o rs
P
paulohbmetal
É pessoal, fui ver com uns colegas aqui e eles tiveram que usar um GenericGenerator (que herda de AbstractPostInsertGenerator e implementa Configurable) para resolver o problema. Ou seja, dentro do Generator faz-se um ‘select curval’ da vida… Vale lembrar que o GenericGenerator é Hibernate e não JPA.
@Entity@Table(name="PAI")publicclassPaiimplementsSerializable{@Id@Column(name="ID_PAI",nullable=false)@GeneratedValue(generator="PaiSeq")@GenericGenerator(name="PaiSeq",strategy="br.com.guj.GeneratorTabajara",parameters={@Parameter(name="sequence",value="PAI_SQ")})privateintid;@OneToMany(mappedBy="pai",fetch=FetchType.LAZY)privateList<Filho>filhos;//gets, sets etc. }
Bom, está aí. Boa pedida para o JPA na próxima versão pois, ninguém merece ficar criando ‘workarrounds’…
acredito que a dica do rapaz ali que disse pra usar IDENTY funcionaria, pois a trigger esta simulando um campo AUTO_INCREMENT. Tive um problema semelhante aqui, facilitei a vida de todos, e utilizei a estrategia SEQUENCE e deletei as triggers.
Na verdade, acho esse lance de usar trigger pra gerar ID, uma verdadeira gambiarra