Map objects through Hibernate with "decentralized" data

Asked

Viewed 1,026 times

2

I do not know if the decentralized term of the title is correct, if someone is not willing to change. But let’s get down to business.

I have a scenario where I am developing a program that manages the supervision of an institution, in the classes of Javaee and Hibernate we made the mapping of the correct classes, created the class Student, for example, put all attributes in it, relationships, etc., follows the code:

Java student.

@Entity
public class Aluno implements Serializable {

    @Id
    @Column(length=11, nullable=false)
    private int cpf;

    @Column(nullable=false)
    private String nome;

    @Column(nullable=false)
    private int rg;

    @Column(length=11,nullable=false)
    private int matricula;

    @Temporal(TemporalType.DATE)
    private Date dataNascimento;

    /* RELACIONAMENTOS */

    @OneToMany(mappedBy="aluno")
    private List<Inscricao> inscricoes;

    @OneToMany(mappedBy="aluno")
    private List<Relatorio> relatorios;

    /* GETTERS AND SETTERS */
    ...
}

Okay, working 100%, but this inside the classroom, now we’re moving on to the implementation part where we’re going to consume data from the institution, only their database doesn’t have a student table like I have in my class, in their database there is a table Student who does not have the name of the student for example but contains the ID of a person, the name of the student is in the table person, and so on, the bank is quite normalized.

Now in practice, how do I manage to consume the data with my current class? What modifications do I make? How to say that the name attribute for example is in the person table? I searched but I couldn’t find, I don’t know if I’m researching the wrong terms, but if anyone can help me, thank you.

1 answer

1


For the table name, you can use the annotation @Table. You can also use @SecondaryTable or @SecondaryTables if the entity is divided into several separate tables. You can use @Inheritance, @DiscriminatorColumn and @DiscriminatorValue to map heritage.

You should make your entity mapping reflect the database and vice versa. If this does not occur, one of the two should be changed. After all, the purpose of the entity and the annotations is exactly to describe to Hibernate/JPA how object-relational mapping occurs, and therefore whether its class Aluno is significantly different from what is in the database, so one of the two must be changed to suit the other.

You can map views if necessary. The reason this is possible is that Hibernate/JPA cannot (or rather does not need) distinguish if it is doing SELECT in a table or a view. However, if you do, at the time it tries to give a INSERT, UPDATE or DELETE, you will have an exception, so only use this if you are sure that these operations should never occur.


Example of use of @Table and @SecondaryTable:

@Entity
@Table(name = "xpto") // O nome da tabela no banco de dados é xpto, embora a entidade se chame Aluno.
@SecondaryTables({
    @SecondaryTable(name = "xpto2", pkJoinColumns = @PrimaryKeyJoinColumn(name = "ALUNO_ID"))
    @SecondaryTable(name = "xpto3", pkJoinColumns = @PrimaryKeyJoinColumn(name = "CHAVE"))
})
public class Aluno implements Serializable {

    @Column(table = "xpto")
    private String foo;

    @Column(table = "xpto2")
    private String bar;

    // ...
}

In this case, you’re saying that the entity Aluno is on the tables xpto, xpto2 and xpto3, being xpto the main table. The corresponding tuples in the table xpto2 and xpto3 are found by the respective primary key fields (which must match the xpto). That is, there is a 1-to-1 relationship between the three (even if the database does not impose integrity restriction, since you are saying this only to Hibernate/JPA). That is, from the point of view of Hibernate/JPA, the tables xpto2 and xpto3 has as PK, the FK of xpto.

If the relationship between these tables is not so simple or the format of the keys differs between one and the other, maybe it is best to use the @OneToOne or something else.


Example of use of @Inheritance strategically JOINED:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Pessoa implements Serializable {
    // ...
}

@Entity
public class Aluno extends Pessoa {
    // ...
}

@Entity
public class Professor extends Pessoa {
    // ...
}

That makes there is a table for Pessoa, one for Aluno and one for Professor, where the primary key of the three have the same format (i.e., from the point of view of Hibernate/JPA, A PK of Aluno is FK of Pessoa and the PK of Professor is FK of Pessoa ). And then:

  • Every tuple inserted in the table Aluno is also on the table Pessoa.
  • The entire tuple inserted in the table Professor is also on the table Pessoa.
  • If a tuple is on the table Pessoa, she may or may not be in Aluno or Professor.

Example of use of @Inheritance strategically TABLE_PER_CLASS:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Pessoa implements Serializable {
    // ...
}

@Entity
public class Aluno extends Pessoa {
    // ...
}

@Entity
public class Professor extends Pessoa {
    // ...
}

That makes there is a table for Aluno and one for Professor. There is no table for Pessoa. Basically the Tebela mapping of Pessoa is copied-and-copied in each of the subclasses.


Example of use of @Inheritance strategically SINGLE_TABLE:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "TIPO", discriminatorType = STRING, length = 20)
public class Pessoa implements Serializable {
    // ...
}

@Entity
@DiscriminatorValue("ALUNO")
public class Aluno extends Pessoa {
    // ...
}

@Entity
@DiscriminatorValue("PROF")
public class Professor extends Pessoa {
    // ...
}

That puts the Alunos and the Professores all in the same table, and such a table should contain all fields of both Aluno how much of Professor. The column TIPO in this example differentiates if the tuple is a Aluno or a Professor. If it is ALUNO is Aluno. If it is PROF is Professor.

  • Yes @Victor, my intention is to transform my class, so that it is according to the table, could you exemplify using these annotations? Assuming there is a student table that has your enrollment, and has a FK for People, and in people has the name of the person.

  • What if I have a view, or a materialized view? Can you simplify, like referencing in the class instead of a table, a view? (I will not insert, only read data)

  • @Joãoneto I edited the answer. What do you think of her now?

  • Congratulations Victor, very good answer! My last question is: How did you say jpa/Hibernate does not differ whether it is a select or view I can in table name by my view name right? thus: @Table(name = view_Alunos), noting that only select.

  • @Joãoneto It’s because it’s time to do the SELECT, no matter if it is view or table, it is completely transparent for the application, including Hibernate/JPA.

  • 1

    Got it, beauty, thanks man. It was great help! : D

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.