Nesta postagem será mostrado como fazer o mapeamento objeto-relacional (ORM) utilizando o hibernate através de um exemplo prático. A idéia principal do exemplo é apenas mostrar como fazer o mapeamento objeto-relacional sem ressaltar conceitos envolvidos. Espera-se que ele sirva como uma referência rápida e objetiva para desenvolvedores.
Para iniciar, vamos definir o modelo de dados relacional através de um diagrama entidade-relacionamento (figura abaixo).
Para melhor visualização clique na imagemAtravés do diagrama entidade-relacionamento acima, podemos extrair alguns casos a serem mapeados.
- Herança – Entidades envolvidas: aluno, professor, pessoa;
- N : M sem atributos intermediários – Entidades envolvidas: disciplina_professor, professor, disciplina;
- 1 : N – Entidades envolvidas: turma, aluno;
- N : M com atributo intermediário – Entidades envolvidas: professor_turma, turma, professor.
Abaixo temos as classes java com o mapeamento objeto-relacional exemplificando os casos citados acima.
Mapeamento de Pessoa:
import static javax.persistence.GenerationType.IDENTITY;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
@SuppressWarnings("serial")
@Entity
@Table(name = "pessoa", catalog = "mapeamentohibernate")
@Inheritance(strategy = InheritanceType.JOINED)
public class Pessoa implements Serializable {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Integer id;
@Column(name = "nome")
private String nome;
// getters e setters omitidos
}
Mapeamento de Aluno:
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
@SuppressWarnings("serial")
@Entity
@Table(name = "aluno", catalog = "mapeamentohibernate")
@PrimaryKeyJoinColumn(name = "id") // id da tabela aluno
public class Aluno extends Pessoa implements Serializable {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "idturma")
private Turma turma;
@Column(name = "matricula")
private String matricula;
// getters e setters omitidos
}
Mapeamento de Professor:
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
@SuppressWarnings("serial")
@Entity
@Table(name = "professor", catalog = "mapeamentohibernate")
@PrimaryKeyJoinColumn(name = "id") // id da tabela professor
public class Professor extends Pessoa implements Serializable {
@Column(name = "formacao")
private String formacao;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "professor")
private Set<ProfessorTurma> professorTurma =
new HashSet<ProfessorTurma>(0);
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "disciplina_professor", catalog = "mapeamentohibernate",
joinColumns = { @JoinColumn(name = "idprofessor", nullable = false,
updatable = false) }, inverseJoinColumns = {
@JoinColumn(name = "iddisciplina", nullable = false, updatable = false) })
private Set<Disciplina> disciplinas = new HashSet<Disciplina>(0);
// getters e setters omitidos
}
Mapeamento de Disciplina:
import static javax.persistence.GenerationType.IDENTITY;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
@SuppressWarnings("serial")
@Entity
@Table(name = "disciplina", catalog = "mapeamentohibernate")
public class Disciplina implements Serializable {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Integer id;
@Column(name = "nome")
private String nome;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "disciplina_professor", catalog = "mapeamentohibernate",
joinColumns = { @JoinColumn(name = "iddisciplina", nullable = false,
updatable = false) }, inverseJoinColumns = {
@JoinColumn(name = "idprofessor", nullable = false, updatable = false) })
private Set<Professor> professores = new HashSet<Professor>(0);
// getters e setters omitidos
}
Mapeamento de Turma:
import static javax.persistence.GenerationType.IDENTITY;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@SuppressWarnings("serial")
@Entity
@Table(name = "turma", catalog = "mapeamentohibernate")
public class Turma implements Serializable {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Integer id;
@Column(name = "descricao")
private String descricao;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "turma")
private Set<ProfessorTurma> professorTurma = new
HashSet<ProfessorTurma>(0);
@OneToMany(fetch = FetchType.LAZY, mappedBy = "turma")
private Set<Aluno> alunos = new HashSet<Aluno>(0);
// getters e setters omitidos
}
Mapeamento de ProfessorTurma:
import java.io.Serializable;
import java.util.Date;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@SuppressWarnings("serial")
@Entity
@Table(name = "professor_turma", catalog = "mapeamentohibernate")
public class ProfessorTurma implements Serializable {
@EmbeddedId
@AttributeOverrides( { @AttributeOverride(name = "idturma", column =
@Column(name = "idturma", nullable = false)), @AttributeOverride(name =
"idprofessor", column = @Column(name = "idprofessor", nullable = false)) })
private Id id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "idturma", nullable = false, insertable = false,
updatable = false)
private Turma turma;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "idprofessor", nullable = false, insertable = false,
updatable = false)
private Professor professor;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "horario", length = 19)
private Date horario;
// getters e setters omitidos
//Id da associacao (chave composta no banco)
@Embeddable
public static class Id implements Serializable {
@Column(name = "idTurma", nullable = false)
private Integer idTurma;
@Column(name = "idProfessor", nullable = false)
private Integer idProfessor;
public Integer getIdTurma() {
return this.idTurma;
}
public void setIdTurma(Integer idturma) {
this.idTurma = idturma;
}
public Integer getIdProfessor() {
return this.idProfessor;
}
public void setIdProfessor(Integer idprofessor) {
this.idProfessor = idprofessor;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + idProfessor;
result = prime * result + idTurma;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Id other = (Id) obj;
if (idProfessor != other.idProfessor)
return false;
if (idTurma != other.idTurma)
return false;
return true;
}
}
}
Note que, no caso N:M que não tem atributo intermediário (tabela disciplina_professor) , não há necessidade de uma classe para representar a associação. No caso em que há atributos intermediários, como o da tabela professor_turma, temos que criar uma classe para representar a associação (classe ProfessorTurma).
O banco de dados utilizado no exemplo foi o MySQL. Quem quiser fazer o download do script do banco basta acessar o link:
http://sites.google.com/site/csscode/Home/mapeamentohibernate.sqlUma dica para quem não tem muita familiaridade com o mapeamento objeto-relacional é usar o
hibernate tools. O hibernate tools trata-se de um plugin do eclipse que auxilia na árdua e massante tarefa de mapear. Vale a pena conferir!!!
Thiago Baesso Procaci