Primarykey, Foreignkey and Unique With JPA

Asked

Viewed 572 times

5

I have the following situation:

  1. Student Entity (id and other)
  2. Entity Evaluation (id and others)
  3. Entity Notaavaliacaoaluno (avaliacaoId, alunoId)

I want to transform the attributes valuedId, alunoId that have relations with entities 1 and 2 into Primarykey and that are Unique.

What is the best way for this mapping?

I’ve checked some forms but be in doubt how to really use.

2 answers

1

1- First you need to map the entity Pupil

@Entity
@Table(name="Aluno") // Eu sempre informo o 'name', mania minha
public class Aluno implements Serializable {
  @Id
  @Column(name = "id")
  private java.lang.Long id; 

  // Demais campos...
}

2 - Mapping Entity Appraisal

@Entity
@Table(name="Avaliacao")
public class Avaliacao implements Serializable {
  @Id
  @Column(name = "id")
  private java.lang.Long id; 

  // Demais campos...
}

3 - Mapping the entity Rating

Before posting the example, it is not always necessary to map these Many-to-Many. I decided to map it because it has information (Which I believe is the student’s grade).

@Entity
@Table(name="NotaAvaliacaoAluno")
public class NotaAvaliacaoAluno implements Serializable {
  @Id
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn( name = "avaliacaoId", referencedColumnName="id")
  private Avaliacao avaliacao; 

  @Id
  @Column(name = "alunoId")
  @JoinColumn(name = "alunoId", referencedColumnName="id")
  private Aluno aluno; 

  // Demais campos...
}

4 - Now we return to the student class and include

 @OneToMany(fetch=fetchType.LAZY, mappedBy="aluno")
 private List<NotaAvaliacaoAluno> notasValiacaoAlunoList;

Ready.

P.S.: As I do not know your model I believe the most appropriate and analyze my response, understand what I suggested and adapt to your case.

0

In all cases you will need a composite key (since on the bank side the PK is composed the JPA must keep this model).

This can be done in two ways:

  1. Id entity + @IdClass

    public class NotaAvaliacaoAlunoPK implements Serializable { 
        private Integer idAluno;
        private Integer idAvaliacao;
        // Outros campos da PK se existirem
    
        // Getters & setters, equals e hashCode
    }
    
    @Entity 
    @IdClass(value=NotaAvaliacaoAlunoPK.class)
    public class NotaAvaliacaoAluno implements Serializable { 
        @Id @Column(name="ID_ALUNO")
        private Integer idAluno;
        @Id @Column(name="ID_AVALIACAO")
        private Integer idAvaliacao;
        // Outros campos da PK se existirem
        @Column
        private String outroCampoQualquer;
    
        // Getters & setters
    }
    
  2. Multiple columns of Ids + @EmbeddedId

    @Embeddable
    public class NotaAvaliacaoAlunoPK implements Serializable { 
        @Column(name="ID_ALUNO")
        private Integer idAluno;
        @Column(name="ID_AVALIACAO")
        private Integer idAvaliacao;
    
        // Getters & setters, equals e hashCode
    }
    
    @Entity 
    public class NotaAvaliacaoAluno implements Serializable { 
        @EmbeddedId
        private NotaAvaliacaoAlunoPK id;
        @Column
        private String outroCampoQualquer;
    }
    

The second decision is to know who boss in Primary Key, whether it is the PK fields directly or whether it is the relationships with Aluno and Avaliacao.

  1. If it’s the fields of Primary key, make relationships do not update the bank:

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="ID_ALUNO", insertable=false, updatable=false)
    private Aluno aluno;
    
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="ID_AVALIACAO", insertable=false, updatable=false)
    private Avaliacao avaliacao;
    
  2. If it is the relationships, have the PK fields not update the bank and the entities of the relationships do (through @PrimaryKeyJoinColumn):

    @Column(name="ID_ALUNO", insertable=false, updatable=false)
    private Integer idAluno;
    @Column(name="ID_AVALIACAO", insertable=false, updatable=false)
    private Integer idAvaliacao;
    
    @ManyToOne(fetch=FetchType.LAZY)
    @PrimaryKeyJoinColumn(name="ID_ALUNO")
    private Aluno aluno;
    
    @ManyToOne(fetch=FetchType.LAZY)
    @PrimaryKeyJoinColumn(name="ID_AVALIACAO")
    private Avaliacao avaliacao;
    

You see I didn’t even get the credit for Element Collections not to further complicate the topic, but the use of collections may be a good idea if the evaluation note values do not make sense outside the context of the parent object.

On the "most correct" way to model a problem, there is no easy answer. It may be that in your application it makes more sense to manipulate the ids directly, maybe it makes more sense to build an ID object. Perhaps it makes more sense to deal with PK values directly (by inserting student ids and evaluations), perhaps the opposite makes sense (to search for the Student object and the Entire Bank Assessment object and set the relationships).

And there are still those who prefer to appeal to a good old map:

@OneToMany(mappedBy="aluno")
@MapKeyColumn(name="ID_AVALIACAO")
private Map<Integer, NotaAvaliacao> notas;

Browser other questions tagged

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