【问题标题】:Map/Access entities with composite key使用复合键映射/访问实体
【发布时间】:2020-04-21 20:23:02
【问题描述】:

在我的应用程序中,我有 3 个核心类,如下所述。

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;

}

而这个 Parametro 类是这 3 个类之间的关系。

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;

}

所以,这是我的问题。我希望能够从它的父类 ExercicioOrdenado 访问 Parametro,但是为了在数据库中区分,Parametro 类需要来自其他两个的引用(Semana , TreinoOrdenado)。

使用我当前的映射,我得到了这个错误:

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])

我可以通过以下方式将参数保存在数据库中:

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

但我无法使用映射从 ExercicioOrdenado 检索。

我不知道这样做的正确方法。

【问题讨论】:

    标签: java spring jpa


    【解决方案1】:

    我想我现在有办法……

    为此,我们可以使用@Embeddable 和@EmbeddedId 注解。 在此链接中有示例。 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;
    
    }
    
    

    我相信这是使用 jpa 创建个性化主键的方法。我没有测试主键中实体的关系。我知道有不止一种形式可以做到这一点。

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

    【讨论】:

    • 您好,但即使使用此代码,我也无法在 ExercicioOrdenado 端映射和检索 Parametro。它仍然说我的外键数量错误。 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]).
    • 嘿,问题是 ParametroId 在类中没有引用,只是一个 id。我编辑答案。再试一次:S。我更改注释。
    • 我阅读了您发布的文档,我想我是按照他们的示例找到了自己的方法。在“Parametro”中,我将映射更改为“@ManyToOne”,在“ExercicioOrdenado”中,我使用“@OneToMany”进行了映射,仅使用“exercicio_id”作为“@JoinColumn”,应用程序停止给出错误,我设法恢复了像这样从数据库中获取数据。然而,为了更新一个实体,它最终复制了数据库中的数据而不是更新,我将进一步调查,但我会在这里回答这个问题。
    猜你喜欢
    • 1970-01-01
    • 2017-09-04
    • 1970-01-01
    • 2021-06-01
    • 1970-01-01
    • 2013-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多