Manytomany mapping with additional column

Asked

Viewed 954 times

-1

In my study project, aimed at controlling football matches, I have the following entities:

Gambler

  • Name;

Departure

  • Date of implementation;
  • Gols pro;
  • Goals against;

I still need to record the goals of the match per player, what should be on the bench this way:

 Jogador               PartidaJogador                Partida
(id,nome)   (jogador_id, partida_id, numeroGols)  (id,data...)

Below the already created classes:

@Entity
public class Jogador implements Serializable {

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

    @NotNull
    private String nome;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    @Override
    public String toString() {
        return nome;
    }

}

@Entity
public class Partida implements Serializable {

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

    @NotNull
    private String adversario;

    @NotNull
    private LocalDate dataRealizacao;

    @Min(0)
    @NotNull
    private Integer golsPro;

    @Min(0)
    @NotNull
    private Integer golsContra;

    @OneToMany
    private Set<PartidaJogador> jogadoresGols = new HashSet<>();

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getAdversario() {
        return adversario;
    }

    public void setAdversario(String adversario) {
        this.adversario = adversario;
    }

    public LocalDate getDataRealizacao() {
        return dataRealizacao;
    }

    public void setDataRealizacao(LocalDate dataRealizacao) {
        this.dataRealizacao = dataRealizacao;
    }

    public Integer getGolsPro() {
        return golsPro;
    }

    public void setGolsPro(Integer golsPro) {
        this.golsPro = golsPro;
    }

    public Integer getGolsContra() {
        return golsContra;
    }

    public void setGolsContra(Integer golsContra) {
        this.golsContra = golsContra;
    }

    public Set<PartidaJogador> getJogadoresGols() {
        return jogadoresGols;
    }

    public void setJogadoresGols(Set<PartidaJogador> jogadoresGols) {
        this.jogadoresGols = jogadoresGols;
    }


}

The basic flow should be the creation of matches, so I need to save the Match object and save the related entity Partidaplayer as well.

How to map the table PartidaJogador with the extra column numeroGols?

  • How about posting the class code Partidajogador?

1 answer

0

You need to create an entity PartidaJogador with a composite primary key referencing the entities' keys Partida and Jogador. Example:

Change the relationship in the table Partida for:

@OneToMany(cascade=CascadeType.PERSIST, mappedBy="partida")
private Set<PartidaJogador> jogadoresGols = new HashSet<>();

Partidajogadorpk

@Embeddable
public class PartidaJogadorPK implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private long jogadorId;

    private long partidaId;

    public PartidaJogadorPK() {}

    public final void setJogadorId(long jogadorId) {
        this.jogadorId = jogadorId;
    }

    public final void setPartidaId(long partidaId) {
        this.partidaId = partidaId;
    }

    public final long getJogadorId() {
        return jogadorId;
    }

    public final long getPartidaId() {
        return partidaId;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + (int) (jogadorId ^ (jogadorId >>> 32));
        result = prime * result + (int) (partidaId ^ (partidaId >>> 32));
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (!(obj instanceof PartidaJogadorPK))
            return false;
        PartidaJogadorPK other = (PartidaJogadorPK) obj;
        if (jogadorId != other.jogadorId)
            return false;
        if (partidaId != other.partidaId)
            return false;
        return true;
    }
}

Partidajogador

@Entity
public class PartidaJogador {

    @EmbeddedId
    private PartidaJogadorPK pk = new PartidaJogadorPK();


    @MapsId("partidaId")
    @ManyToOne
    @JoinColumn(name="partidaId", referencedColumnName="id")
    private Partida partida;


    @MapsId("jogadorId")
    @ManyToOne
    @JoinColumn(name="jogadorId", referencedColumnName="id")
    private Jogador jogador;

    private int numeroDeGols;

    public final Partida getPartida() {
        return partida;
    }

    public final void setPartida(Partida partida) {
        this.partida = partida;
    }

    public final Jogador getJogador() {
        return jogador;
    }

    public final void setJogador(Jogador jogador) {
        this.jogador = jogador;
    }

    public final int getNumeroDeGols() {
        return numeroDeGols;
    }

    public final void setNumeroDeGols(int numeroDeGols) {
        this.numeroDeGols = numeroDeGols;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((pk == null) ? 0 : pk.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (!(obj instanceof PartidaJogador))
            return false;
        PartidaJogador other = (PartidaJogador) obj;
        if (pk == null) {
            if (other.pk != null)
                return false;
        } else if (!pk.equals(other.pk))
            return false;
        return true;
    }
}

Example of use:

em.getTransaction().begin();

Jogador jogador = new Jogador();
jogador.setNome("Presunto");
em.persist(jogador);


Partida partida = new Partida();
partida.setAdversario("Tabajara");
partida.setDataRealizacao(LocalDate.now());
partida.setGolsPro(3);
partida.setGolsContra(2);

em.persist(partida);

PartidaJogador partidaJogador = new PartidaJogador();
partidaJogador.setJogador(jogador);
partidaJogador.setPartida(partida);
partidaJogador.setNumeroDeGols(2);

//em.persist(partidaJogador);

Set<PartidaJogador> partidaJogadores = new HashSet<>();
partidaJogadores.add(partidaJogador);

partida.setJogadoresGols(partidaJogadores);

em.getTransaction().commit();

Addendum: It may be interesting for you to consider whether the goal should also be treated as an entity, since it has its own relevant attributes, such as when it was scored, author, author of the assistance, etc.

  • In this case you have a problem in my view: you are saving the match without the information of the players. As I put the question, I wish to save the match directly, with the set of Partidaplayer inside it.

  • @Murillogoulart to Partida needs to be saved first, since in the table PartidaJogador is referenced the id of Partida. If the PartidaJogador was saved first, there would be an inconsistency, since she would not have a Partida to reference. What you can do to "circumvent" this, is to use a "Cascadetype.PERSIST" in the relationship in the entity Partida. Remember that this transaction must be atomic, if a Partida is not persisted, the PartidaJogador neither.

Browser other questions tagged

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