Create table TAB_Pessoa
(
IDPessoa int4 NOT NULL DEFAULT nextval("seqPessoa"),
NomePessoa varchar(100),
IDPessoa_Pai int,
PRIMARY KEY("IDPessoa")
)
go
ALTER TABLE TAB_Pessoa
ADD CONSTRAINT "TAB_Pessoa_IDPessoa_Pai_fkey"
FOREIGN KEY("IDPessoa_Pai")
REFERENCES TAB_Pessoa("IDPessoa")
go
Notem que o campo IDPessoa_Pai faz referencia (chave estrangeira com a propria tabela de pessoas) isso no banco de dados ele faz na boa;
No Java a classe Pessoa ficou ± assim (atentem para o atributo Pai que é do tipo Pessoa):
public class Pessoa
{
private int IDPessoa;
private String NomePessoa;
private Pessoa Pai;
//gets
public int getIDPessoa() { return IDPessoa; }
public String getNomePessoa() { return NomePessoa; }
public Pessoa getPai() { return Pai; }
//Sets
public void setNomePessoa(String nomePessoa) { NomePessoa = nomePessoa; }
public void setIDPessoa(int pessoa) { IDPessoa = pessoa; }
public void setPai(Pessoa pai) {Pai = pai; }
}
Estou com duvida agora como configurar o Hibernate para que ele entenda e trate essa chave estrangeira com a propria tabela;
Eu quero por exemplo que ao tentar excluir uma pessoa o hibernate verifique se esta pessoa é pai de alguma outra pessoa e não permita a exclusão
Já fiz varias tentativas, mas sem sucesso, uma delas o hibernate deixa deletar depois qdo tenta fazer o comitt no banco e o banco não permite (porque existe uma FOREIGN KEY) o Hibernate perde a sincronia. Em outra situação (conforme configuração abaixo) quando eu tento exluir uma pessoa ele saiu exluindo os Pais (e não os filhos)!!!
Estou trabalhando num projeto grande da Empresa que ja optaram pelo hibernate, até consegui um paliativo colocando na action uma verificação se pode ou não pode deletar o registro(objeto), mas gostria de resolver isso através do hibernate, acho que existe como fazer eu é que não estou sabendo qual a configuração ideal.
Agora entendi o que vc quis dizer, mas é o seguinte:
Eu ja uso o Hib 3, porem não utilizo o esquema de Annotations, estamos utilizando os arquivos hbm.xml, acredito que no meu caso seja melhor procurar a solução do meu problema dentro desta estrutura, pois senão terei que mudar a forma de trabalhar e ainda não ter garantias de que o o problema q eu tenho hoje possa ser sanado com Annotations.
De qualquer forma valew pela ajuda,
E fico no aguardo se alguem tem alguma dica de como fazer o mapeamento correto para o meu caso.
Espero nao estar falando besteria, mas, seu bean esta criado exatamente como a tabela, porem acho q vc poderia criar + um atributo no bean com referencia para os filhos, sem altera sua tabela. ex:
[code]public class Pessoa
{
private int IDPessoa;
private String NomePessoa;
private Pessoa Pai;
private List filhos;
...
}[/code]
assim, vc carregando uma “Pessoa”, é possível navegar pra cima e para baixo na hierarquia.O list filhos tambem seria um mapeamento pra tb Pessoa, mas ali ao invés de vc carregar a foreign key, vc carrega um bag onde seu id é foreign key, intendeu.
Nao sei que tipo de controle do delete vc quer fazer pelo hibernate, mas assim é possivel vc verificar se a pessoa tem filhos e vc deleta-los antes de se deletar, isso pode ser feito manual ou automaticamente.
se vc mapear o list com cascade=“all-delete-orphan”, quando vc excluir um filho do list, o delete dele no banco é feito automaticamente pelo hibernate, e se vc deletar a pessoa, os filhos sao deletados automaticamente até o ultimo nível a partir da pessoa carregada, tudo feito automaticamente pelo hibernate.
Porém, se vc quer que uma pessoa que tem filhos não seja deletada, dai não sei como fazer essa verificaçao automaticamente pelo hibernate, uma forma seria deixar o delete falhar no banco(como vc ja tinha citado) ou então através do list filhos, vc verificar se o size() dele é maior que 0.
A Situação que eu quero controlar é exatamente não permitir a exclusão de “Pais” com “Filhos” (Afinal alguem precisa alimentar esta criançada rsrsrs)
Coloquei na minha action, paliativamente um controle que faz ± o q vc falou pego um list dos filhos, e quando existe algum registro eu gero uma excesão proibindo a exclusão, mas acho que o hibernate deveria fazer isso.
o fato é que se eu deixar o “delete” chegar no hibernate ele deleta da persistencia dele, mas qdo tenta fazer o commit no banco é que ele recebe a exception do banco proibindo a exclusão, é ai que o hibernate perde a sincronia, afina pra ele (hibernate) o registro ja era considerado excluido!
E se vc fizer o seguinte, no momento que falhar o commit, vc der um load novamente no objeto, dai ele vai sincronizar novamente o objeto!
try
{
delete(obj);
commit();
}
catch(Exception e)
{
rollback();
obj = load();
}
Algo nesse sentido!
Outra forma eu não conheço, pra te dizer a verdade. Se existisse, seria interessante.
Se tivesse como fazer como vc disse, de não executar o delete quando houver filhos, seria mto bom, mas acho q nao existe como fazer isso diretamente, pq o hibernate manipula o objeto, mas nao conhece o seu estado!
Na verdade, sei lá!!
bom eu vou deixar o meu “paliativo” ganhar status de “Definitivo”, é a unica entidade do sistema que vai ter esse tipo de associação (objeto que depende dele mesmo) então vou manter o controle da exclusão na action;
Agora estou sem tempo para testes, mas assim q sobrar um tempinho, quero testar assim:
Duplicar as configurações do hibernate (hbm.xls e classe pojo) apontando para mesma tabela, só pra “enganar” o hibernate, acredito que ele deva tratar e perssistir outra coleção de dados como se fosse outra tabela e fazer o controle da forma que eu quero, pois tenho outras associações do tipo chave estrangeira que o hibernate gerencia na boa.