0

In my application I have 3 core classes as described below.

public class Semana {

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

    private Integer series;

    private String observacao;

    private Integer ordenacao;


    @OneToMany(mappedBy = "semana")
    @JsonBackReference
    @OrderBy("ordenacao asc ")
    private List<TreinoOrdenado> treinoOrdenados;
 }
public class TreinoOrdenado {

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

    @ManyToOne
    @JoinColumn(name = "id_semana")
    private Semana semana;

    @ManyToOne
    @JoinColumn(name = "id_treino")
    private Treino treino; // can be repeated in the database but with different "ordenacao" 

    private Integer ordenacao;

}
@Table(name = "exercicio_ordenado")
public class ExercicioOrdenado {

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

    @ManyToOne
    @JoinColumn(name = "id_treino")
    @JsonBackReference
    @ToString.Exclude
    private Treino treino;

    @ManyToOne
    @JoinColumn(name = "id_exercicio")
    private Exercicio exercicio;

    private Integer ordenacao;

   @ManyToOne
   @JoinTable(name = "parametro")
   private Parametro parametro;

}

And this Parametro class which is a relationship between those 3 classes.

public class Parametro {

    @EmbeddedId
    private ParametroId parametroId = new ParametroId();

    @MapsId("semana")
    @OneToOne
    @JoinColumn(name = "semana_id")
    private Semana semana;

    @MapsId("treino")
    @OneToOne
    @JoinColumn(name = "treino_id")
    private TreinoOrdenado treino;

    @MapsId("exercicio")
    @OneToOne
    @JoinColumn(name = "exercicio_id")
    private ExercicioOrdenado exercicio;

    private Integer series;

    private String repeticoes;

    private String observacao;

}
public class ParametroId implements Serializable {

    @Column(name = "semana_id")
    private Long semana;

    @Column(name = "treino_id")
    private Long treino;

    @Column(name = "exercicio_id")
    private Long exercicio;

}

So, here is my problem. I want to be able to access the Parametro from it's parent class ExercicioOrdenado, but in order to be distinguishable in the database the class Parametro needs the reference from the other two (Semana, TreinoOrdenado).

With my current mapping I got this error:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource 
[org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.MappingException: Foreign key (FK73ewcy2r50kw71o4he51dkolv:parametro 
[parametro_exercicio_id,parametro_semana_id,parametro_treino_id])) must have same number of columns as the referenced primary key (parametro [id])

I can persist paremetros in the database with:

   parametros.setSemana(semana);
   parametros.setExercicio(exercicioOrdenado);
   parametros.setTreino(treinoOrdenado);
   parametroRepository.save(parametros);

But I can't retrieve from ExercicioOrdenado with the mapping.

I don't know the right approach to do this.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Liddell
  • 1
  • 3

1 Answers1

0

I think i now a way...

To do this we can use @Embeddable and @EmbeddedId annotation. In this link have exemples. https://www.baeldung.com/jpa-composite-primary-keys

@Entity
public class Parametro {

    @EmbeddedId
    private ParametroId parametroId;


    @OneToOne
    @JoinColumn(name = "exercicio_id")
    @ForeignKey(name = "fk_exercicio_id")
    private ExercicioOrdenado exercicio;    

    @OneToOne
    @JoinColumn(name = "semana_id")
    @ForeignKey(name = "fk_semana_id")
    private Semana semana;


    @OneToOne
    @JoinColumn(name = "treino_id")
    @ForeignKey(name = "fk_treino_id")
    private TreinoOrdenado treino;

    private Integer series;

    private String repeticoes;

    private String observacao;
}

@Embeddable
public class ParametroId {


    private log id;

    private log semana;


    private log treino;

    private log exercicio;

}

I believe that this is the way to create a personalized primary key using jpa. I have not tested the relationships of entities in the primary key. I know that there is more than one form to do that.

JPA @OneToOne with Shared ID -- Can I do this Better?

  • Hi, but even with this code I can't map and retrieve _Parametro_ on the _ExercicioOrdenado_ side. It still say I have the wrong number of foreign keys. `foreign key (FK73ewcy2r50kw71o4he51dkolv:parametro [parametro_exercicio_id,parametro_semana_id,parametro_treino_id])) must have same number of columns as the referenced primary key (parametro [id])`. – Liddell Apr 21 '20 at 22:42
  • Hey, in thik the problem are ParametroId dont have the reference in class, just a id. I editing the answer. Try again :S. I change the anotations. – Andrey Rosa Apr 21 '20 at 23:31
  • I read the documentation you posted and I think I found my way by following their example. In "Parametro" I changed the mapping to '@ManyToOne' and in "ExercicioOrdenado" I did the mapping with '@OneToMany' using only "exercicio_id" as '@JoinColumn', the application stopped giving an error and I managed to recover the data from the database like this. However, to update an entity, it ended up duplicating the data in the database instead of updating, I will investigate further, but I will give this question here as answered. – Liddell Apr 23 '20 at 00:41