Tipos de Herança – Hibernate

Bom, já tive algumas vezes a necessidade de pesquisar algumas forma de se fazer herança utilizando hibernate. Vou mostrar nesse post 3 modos:

  1. SINGLE_TABLE
  2. JOINED
  3. TABLE_PER_CLASS

1 – SINGLE_TABLE

O SINGLE_TABLE cria apenas uma simples tabelas com todos os campos existentes na hierarquia classes que você criou.

Vamos a um exemplo porque daí fica mais fácil.

A.java

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
 
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class A
{
    @Id
    private Integer id;
    private String name;
    private Double decimalValue;
    private String stringValue;
 
    public A()
    {
    }
 
    public Integer getId()
    {
        return id;
    }
 
    public void setId(Integer id)
    {
        this.id = id;
    }
 
    public String getName()
    {
        return name;
    }
 
    public void setName(String name)
    {
        this.name = name;
    }
 
    public Double getDecimalValue()
    {
        return decimalValue;
    }
 
    public void setDecimalValue(Double decimalValue)
    {
        this.decimalValue = decimalValue;
    }
 
    public String getStringValue()
    {
        return stringValue;
    }
 
    public void setStringValue(String stringValue)
    {
        this.stringValue = stringValue;
    }
}

B.java

import javax.persistence.Entity;
 
@Entity
public class B extends A
{
    private String bString;
    private Double bDouble;
    private Integer bInteger;
 
    public B()
    {
    }
 
    public String getbString()
    {
        return bString;
    }
 
    public void setbString(String bString)
    {
        this.bString = bString;
    }
 
    public Double getbDouble()
    {
        return bDouble;
    }
 
    public void setbDouble(Double bDouble)
    {
        this.bDouble = bDouble;
    }
 
    public Integer getbInteger()
    {
        return bInteger;
    }
 
    public void setbInteger(Integer bInteger)
    {
        this.bInteger = bInteger;
    }
}

C.java

@Entity
public class C extends A
{
    private String cString;
    private Double cDouble;
    private Integer cInteger;
 
    public C()
    {
    }
 
    public void setcString(String cString)
    {
        this.cString = cString;
    }
 
    public String getcString()
    {
        return cString;
    }
 
    public void setcDouble(Double cDouble)
    {
        this.cDouble = cDouble;
    }
 
    public Double getcDouble()
    {
        return cDouble;
    }
 
    public void setcInteger(Integer cInteger)
    {
        this.cInteger = cInteger;
    }
 
    public Integer getcInteger()
    {
        return cInteger;
    }
}

Nesse caso geramos apenas uma tabela simples com todos os campos contidos nas três classes que mostramos acima (A,B e C). Veja a imagem:

Quando você buscar no banco pelo objeto C ele limitará a consulta por Dtype = ‘C’. Isso te dá um ganho de não precisar fazer um JOIN, porém cada nova classe que extender a classe A acrescentará a tabela os novos campos.

 

2 – JOINED

Para fazer a herança do tipo JOINED é necessário apenas trocar de InheritanceType.SINGLE_TABLE para InheritanceType.JOINED na classe pai (A.java) e o resultado será:

Quando selecionarmos um objeto da classe C o hibernate fará um JOIN com a classe A utilizando o campo id. Se você fizer uma busca por A ele fará JOIN com todas as tabelas filhas e isso pode não ter um bom desempenho dependendo da sua modelagem.

3 – TABLE_PER_CLASS

Para utilizar o TABLE_PER_CLASS é necessário trocar para InheritanceType.TABLE_PER_CLASS. Utilizando essa estratégia o hibernate criará uma tabela para cada classe, onde cada classe filha terá também os campos da classe pai, como mostra a imagem abaixo:

Essa estratégia também não necessita da utilização de JOIN.

Conclusão

Essas são as estratégias oferecidas pelo hibernate, porém existem outras implementações, como por exemplo a utilização de um descriminador de tipagem.

Outra abordagem existente é se você precisa de herança mas não necessita criar uma tabela para a classe pai é a utilização da anotação @MappedSuperClass. Utilizando essa anotação o hibernate criará apenas uma tabela para cada classe filha e inserirá os campos da classe pai na tabela da classe filha.

Utilize a estratégia que melhor se encaixe a sua modelagem, pois não existe uma melhor e outra pior, e sim uma para cada caso.

Fonte: http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#d0e1168
Fonte: http://blog.v-s-f.co.uk/2010/12/inheritance-type-with-hibernate/

 

3 responses to “Tipos de Herança – Hibernate

  1. E usando Joined com mais uma classe que extenda outra classe filha, exemplo se tivessemos Class D que extende a Class B, como ficaria?

  2. Jr… Nesse caso teríamos A >> B >> D certo? Se fizéssemos um select na classe A ele faria JOIN com todas as classes filhas (B, C e D). Agora… se você fizesse um select na classe B acredito que o hibernate não faria JOIN com a classe C. Teríamos que montar esse exemplo e consultar a query gerada para se ter certeza.

  3. Estou trabalhando com postegres e minha dúvida é que nessa estratégia como se encaixa o Sequence

    @GeneratedValue(generator=”seq_”,strategy=GenerationType.SEQUENCE)

    Tem alguma maneira de cada classe implementar o seu proprio independe da ?

Leave a Reply

Your email address will not be published. Required fields are marked *