Single_Table atualizar

19 respostas
rafaelevoinfo

Olá pessoal, já estou a algum tempo martelando neste problema, por isso peço a ajuda de vocês.

E o seguinte: Tenho 4 classes.
Usuario

@Entity
@Table(name = "usuario")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "permissao", discriminatorType = DiscriminatorType.INTEGER)
public class Usuario implements  Serializable {
...
}

Visitante

@Entity
@Table
@DiscriminatorValue(value = "1")
public class Visitante extends Usuario {
}

Entrevistador

@Entity
@Table
@DiscriminatorValue(value = "2")
public class Entrevistador extends Usuario {
}

Administrador @Entity @Table @DiscriminatorValue(value = "3") public class Administrador extends Usuario { }

Se quando eu tento alterar algum valor eu alterar o campo permissao, ele ao invez de atualizar no banco faz é cadastrar um novo registro.
Já verifiquei se estava pegando outro Id, mas não estava. No momento da execução do método de alterar todos os campos estão iguais, exceto o permissão.

Sabem se existe alguma maneira de alterar ao invez de inserir outro registro?

Obrigado

19 Respostas

Hebert_Coelho

Não se se é isso mas… pq vc tem @Table em todas as suas classes?

rafaelevoinfo

Na verdade acho que eles não interferem em nada mas tirei para descargo de consciência. Porém, não mudou nada.
Continua cadastrando outro registro quando eu tento alterar.

RicardoYukito

O hibernate é chato com herança …

Se não estou enganado, o DescriminatorColumn, voce nao pode alterar… é gerenciado pelo proprio framework ao persistir a instancia da classe.
Se voce precisa por exemplo, gravar a instancia de um usuário, e posteriormente tentar fazer esse usuário virar um visitante, crie um relacionamento entre as classes e esqueça usar herança.
Já apanhei com isso tbm, e nao achei solução. me corrija se estiver errado …
Atenciosamente.

Hebert_Coelho

Pode alterar pode, já até fiz isso nesse post: Uma tabela por herança

Suas sub-classes estão definindo algum @Id?

rafaelevoinfo

Pode alterar pode, já até fiz isso nesse post: url=http://uaihebert.com/?p=441]Uma tabela por herança[/url]

Suas sub-classes estão definindo algum @Id?

Não, minhas sub-classes não estão definindo nenhum @Id.
No link que você passou não entendi como que vou fazer para alterar meu registro. Ex.: como fazer para um Entrevistador se tornar um Administrador?
de todas as maneiras que tentei, sempre que altero o tipo dele, ao invez de dar um update o hibernate faz um insert.

Será que o único jeito é excluir o registro e então cadastrar novamente?

Hebert_Coelho

rafaelevoinfo:
Não, minhas sub-classes não estão definindo nenhum @Id.
No link que você passou não entendi como que vou fazer para alterar meu registro. Ex.: como fazer para um Entrevistador se tornar um Administrador?
de todas as maneiras que tentei, sempre que altero o tipo dele, ao invez de dar um update o hibernate faz um insert.

Será que o único jeito é excluir o registro e então cadastrar novamente?


Mano, muito estranho isso. Até onde eu sei vc poderia alterar na moral.

Se você realizar um find e depois um merge seguido um do outro sem alterar dado algum, ele vai inserir outro registro?
Se você alterar qualquer outro campo sem ser o campo permissao, ele tb insere outro?

Como você definiu o campo ID da sua super classe (Usuario)?

rafaelevoinfo

Se você realizar um find e depois um merge seguido um do outro sem alterar dado algum, ele vai inserir outro registro?
Se você alterar qualquer outro campo sem ser o campo permissao, ele tb insere outro?

Como você definiu o campo ID da sua super classe (Usuario)?

Não… ele só insere outro registro se eu alterar o campo permissão. Caso altere outro campo ele realiza o update normalmente.

o id na classe Usuario ficou assim:

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
Hebert_Coelho

Esse campo permissão está na super classe?

Teria como você postar a classe toda?

rafaelevoinfo

Então jakefrog, estou meio confuso com relação a este campo permissão… olhe minha classe

@Entity
@Table(name = "usuario")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "permissao", discriminatorType = DiscriminatorType.INTEGER)
/**
 * Classe pai para todos os usuarios do sistema
 * 1 - Visitante
 * 2 - Entrevistador
 * 3 - Administrador
 */
public class Usuario implements InterfaceTabela, Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    @Column
    private String nome;
    @Column(unique=true)
    private String login;
    @Column
    private String telefone;
    @Column
    private String email;
    @Column
    private String senha;
    @Column(updatable = false, insertable = false, name = "permissao")
    protected Integer permissao;
    @Column
    private Boolean excluido;

   //getters, setters, equals e hascode
  ...
}

Acabei de descobrir que mesmo que eu retire o campo ‘private Integer permissao’ o hibernate irá cria-lo no banco. Porém ja testei isso tbm, retirei ele e fiz a mesma coisa. Novamente ele inseriu outro registro.

Hebert_Coelho

Ontem eu estava lendo o livro e caiu justamente sobre herança.

Mano, vamos lah:

  1. protected Integer permissao; - Esse campo aparece em outras classes? Se sim, deixa só na superclasse pq é bizarro você retirar e ele criar assim mesmo. Se você eliminar de tudo, veja c não tem EAR/WAR antigo no seu servidor e vc está sendo vítima de cache.
  2. @Column(updatable = false, insertable = false, name = “permissao”) se vc deixa esse valor, ele deveria dar erro na hora do update. Não deveria nem funcionar, sério mesmo.
  3. No livro estava falando que não devemos utilizar a super classe para persistência apenas classes filhas. Faz o teste não na classe pai, mas na filha para ver qual o resultado.
rafaelevoinfo
1) protected Integer permissao; - Esse campo aparece em outras classes? Se sim, deixa só na superclasse pq é bizarro você retirar e ele criar assim mesmo. Se você eliminar de tudo, veja c não tem EAR/WAR antigo no seu servidor e vc está sendo vítima de cache. 2) @Column(updatable = false, insertable = false, name = "permissao") se vc deixa esse valor, ele deveria dar erro na hora do update. Não deveria nem funcionar, sério mesmo.
Não sei se entendi direito o que você quis dizer, mas é o seguinte. se eu coloco a classe assim:
@Entity  
@Table(name = "usuario")  
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)  
@DiscriminatorColumn(name = "permissao", discriminatorType = DiscriminatorType.INTEGER)  
/** 
* Classe pai para todos os usuarios do sistema 
* 1 - Visitante 
* 2 - Entrevistador 
* 3 - Administrador 
*/  
public class Usuario implements InterfaceTabela, Serializable {  
    //outros atributos
     ...
    @Column(updatable = false, insertable = false, name = "permissao")  
    protected Integer permissao;  
    @Column  
    private Boolean excluido;  
  
   //getters, setters, equals e hascode  
  ...  
}
Ele vai gerar no banco um campo chamado permissão. E se eu colocar o codigo assim:
@Entity  
@Table(name = "usuario")  
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)  
@DiscriminatorColumn(name = "permissao", discriminatorType = DiscriminatorType.INTEGER)  
/** 
* Classe pai para todos os usuarios do sistema 
* 1 - Visitante 
* 2 - Entrevistador 
* 3 - Administrador 
*/  
public class Usuario implements InterfaceTabela, Serializable {  
    //outros atributos
     ...
    /*@Column(updatable = false, insertable = false, name = "permissao")  
    protected Integer permissao;  */
    @Column  
    private Boolean excluido;  
  
   //getters, setters, equals e hascode  
  ...  
}
Ele também vai gerar no banco um campo chamado permissão.
3) No livro estava falando que não devemos utilizar a super classe para persistência apenas classes filhas. Faz o teste não na classe pai, mas na filha para ver qual o resultado.
na verdade eu nunca crio uma instancia da classe Usuario(tenho ate que lembrar de marca-la como abstract), sempre criou das suas sub-classes (Visitante, Entrevistador, Administrador). Mas vou seguir o conselho do Ricardo (fazer isso de outra maneira que não envolva herança), pois estava fazendo assim apenas por motivos didáticos (queria ver como funcionava o Single_Table).

De qualquer forma, muito obrigado pela sua ajuda.

Hebert_Coelho

Se vc comenta o código do profissão e mesmo assim o campo é gerado, tem coisa errada.

Como que o hibernate vai achar esse campo do nada e criar??

Verifique get/set ou alguma outra coisa.

Deve ter algum código perdido por aí que deve estar criando esse campo.

rafaelevoinfo

Acredito que ele saiba por causa do

é o mesmo caso do exemplo da URL que você passou. Em nenhum lugar daquelas classes é definido o atributo FROM_CLASS, porém ele é criado automaticamente pelo hibernate no banco.

Hebert_Coelho

Vc ta definindo o campo discriminator com o mesmo nome a um campo normal??

E é esse valor que você ta tentando alterar? É isso?

Eu creio que o único modo de alterar, seria se você fizesse um update na unha nesse registro viu.

rafaelevoinfo

Na verdade eu não sabia que quando se define o campo discriminator o hibernate ja cria este campo automaticamente, por isso eu tinha criado o atributo permissão.

Exatamente isso! Eu queria alterar o campo permissão, mas não altera, sempre que mudo ele o hibernate faz um INSERT ao invés de um UPDATE.

Isso eu não tentei. Se tiver tempo vou tentar depois.

Obrigado.

Hebert_Coelho

Na verdade eu não sabia que quando se define o campo discriminator o hibernate ja cria este campo automaticamente, por isso eu tinha criado o atributo permissão.

Exatamente isso! Eu queria alterar o campo permissão, mas não altera, sempre que mudo ele o hibernate faz um INSERT ao invés de um UPDATE.

Isso eu não tentei. Se tiver tempo vou tentar depois.

Obrigado.
Desculpe só agora perceber que era o mesmo nome do discriminator.
Sim, o proprio hibernate já cria o campo para você.

Mas pq vc quer alterar o tipo da herança do objeto?

rafaelevoinfo

jakefrog:

Mas pq vc quer alterar o tipo da herança do objeto?

Trabalho em uma ONG e este sistema será usado pelos funcionários aqui, mas também poderá ser utilizado por algum aluno da faculdade que quiser vir aqui fazer alguma pesquisa. Estes alunos seriam cadastrados como visitantes, o que iria limitar suas permissões no sistema. Mas suponha que este aluno queira ser voluntario em algum trabalho de pesquisa realizado aqui pela ONG. Ele deverá ter permissões de entrevistador para poder realizar as entrevistas e depois sincronizar os dados do seu smartphone para o servidor.
Obvio que eu poderia simplesmente exclui-lo e cadastrar novamente, mas eu queria não ter que preencher todos os dados da pessoa novamente.
Esta situação também irá ocorrer pouquíssimas vezes (se ocorrer), mas já que eu estou fazendo este sistema para aprender, resolvi colocar esse requisito para tornar as coisas mais interessantes… rsrsrs

Hebert_Coelho

rafaelevoinfo:
jakefrog:

Mas pq vc quer alterar o tipo da herança do objeto?

Trabalho em uma ONG e este sistema será usado pelos funcionários aqui, mas também poderá ser utilizado por algum aluno da faculdade que quiser vir aqui fazer alguma pesquisa. Estes alunos seriam cadastrados como visitantes, o que iria limitar suas permissões no sistema. Mas suponha que este aluno queira ser voluntario em algum trabalho de pesquisa realizado aqui pela ONG. Ele deverá ter permissões de entrevistador para poder realizar as entrevistas e depois sincronizar os dados do seu smartphone para o servidor.
Obvio que eu poderia simplesmente exclui-lo e cadastrar novamente, mas eu queria não ter que preencher todos os dados da pessoa novamente.
Esta situação também irá ocorrer pouquíssimas vezes (se ocorrer), mas já que eu estou fazendo este sistema para aprender, resolvi colocar esse requisito para tornar as coisas mais interessantes… rsrsrs
Pô mano mas aí eu não acho que herança seja a solução.

Seria mais fácil um Enum contento o tipo de usuário que o cara é. =/

A herança faria sentido caso a classe que herda tivesse que ter algum comportamento a + do que um usuário normal.

Caso tenha esse comportamento, mantenha a herança e crie o enum chamado Perfil (que é normal em empresas). Pois é o perfil que define o acesso do usuário aos recursos.

rafaelevoinfo

Foi exatamente isso que eu fiz, depois que vi que não iria dar certo esse negocio… :smiley:
Mas é como eu disse, estou fazendo este sistema e aproveitando para aprender a usar o hibernate. Mas admito que este não era o melhor cenário para tentar isso.

Mas é isso ai, com isso descobri mais uma situação onde não usar Herança… rsrss

Novamente, muito obrigado pela ajuda e paciência.

Criado 9 de janeiro de 2012
Ultima resposta 10 de jan. de 2012
Respostas 19
Participantes 3