[RESOLVIDO] JPA - Obter chave gerada por Sequence em Trigger

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.

Segue o código para analisarem:

@Entity
@Table(name = "PAI")
@SequenceGenerator(name = "PaiSeq", sequenceName = "PAI_SQ", allocationSize = 1)
public class Pai implements Serializable {

    @Id
    @Column(name="ID_PAI", nullable = false)    
    @GeneratedValue(generator="PaiSeq", strategy = GenerationType.SEQUENCE)
    private long id;

   @OneToMany(mappedBy="pai", fetch = FetchType.LAZY)
    private List<Filho> filhos;

//gets, sets etc.
}

Como já devem imaginar, isso não é negociável com os DBA’s.Portanto, tenho que me virar. Alguma luz?

Obrigado!

Pode-se primeiro persistir o pai e depois setar os filhos e “merdiar” o pai novamente.

Li novamente e agora entendi a sua dúvida…pensando rs…

É justamente isso que estou fazendo.

Paz e bem!

Ah tá. rsrsrs…

Paz e bem!

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?

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?

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!

[quote=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?[/quote]

Isso, o objeto Pai está ficando com o primeiro ID e não o gerado pela Trigger.

Paz e bem!

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!

[quote=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![/quote]

É, 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!

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.

Mas até ai desacopla-los e depois acopla-los não é um problema e sim a sequence :stuck_out_tongue:

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?

   @Id  
   @Column(name="ID_PAI", nullable = false)      
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private long id;

flw

É 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.

[quote=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.[/quote]

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

AUTO, deixará o provedor escolher a melhor estrategia para o banco de dados inferior, no caso se for o oracle provavelmente a escolha é SEQUENCE.

[quote=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?

   @Id  
   @Column(name="ID_PAI", nullable = false)      
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private long id;

flw[/quote]

Acabei copiando errado, não AUTO mas sim IDENTITY. Isso porque com esta trigger esta coluna funciona como se fosse autoincremento.

Não lembro se Oracle suportam colunas de identidade… tem de testar.

Acho que não, de qualquer forma acho que o problema continuaria.