持久保存实体对象,其中外键是复合主键Spring Boot,Spring JPA的一部分-引发错误

问题描述

@Entity
@Table(name = "pharmacy",schema = "master_relational_db")
public class Pharmacy {

    @Id @Column(name = "id_pharmacy",columnDeFinition = "INT(3)") private Integer id;
    ... some other columns
    
    @OnetoMany(mappedBy = "pharmacy",cascade = CascadeType.ALL,fetch = FetchType.LAZY)
    private List<Article> articles;

以上类别代表药房,并且具有简单的整数ID。

@Entity
@Table(name = "article",schema = "master_relational_db")
public class Article {

    @EmbeddedId private ArticleId id;
    @Column(name ="name",length = 512,nullable = false) private String name;
    ... some other columns

    @MapsId("id_article_pharmacy")
    @ManyToOne(cascade = {CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH},fetch = FetchType.LAZY)
    @JoinColumn(name ="article_pharmacy_fk")
    private Pharmacy pharmacy;

上述类是代表属于特定药房的商品的类。它与药房有@ManyToOne关系,并且外键也是文章的嵌入式(ArticleId)主键的一部分。

@Embeddable
public class ArticleId implements Serializable {

    @Column(name = "id_article")
    private Integer idArticle;

    @Column(name = "id_article_pharmacy")
    private Integer idPharmacy; //this is filled with foreign key (this is id of linked pharmacy)

    public ArticleId(Integer idArticle,Integer idPharmacy){
        this.idArticle = idArticle;
        this.idPharmacy = idPharmacy;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof ArticleId)) return false;
        ArticleId that = (ArticleId) obj;
        return Objects.equals(getIdPharmacy(),that.getIdPharmacy()) &&
                Objects.equals(getIdArticle(),that.getIdArticle());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getIdArticle(),getIdPharmacy());
    }
}

以上类代表商品的ID,它具有一些整数商品ID(id_article)和药房ID,这也是表示ManyToOne与药房关系的外键。 我运行上面的代码,并根据需要在数据库中创建表。我用一些数据填充了药房表格,但是当我要创建新文章并将其与某些药房问题链接时,就会出现。下是用于添加文章代码,此代码是我用于添加文章的服务(@Service)方法的一部分:

    @Transactional
    public void addArticle() throws sqlException {

       Article toSave = new Article(...constructor for setting fields that are not pk or fk);

            Pharmacy ap = pharmacyRepository.findById(idOfPharmacy).get(); //we get pharmacy //with some id that we want to link this new article with.
//I debug this code and findById returns wanted pharmacy from DB.
            

            ArticleId id = new ArticleId(10,ap.getId());//we create ArticleId with id_article = 10 and id_article_pharmacy = (id of ap object (id of pharmacy that we get from findById method))

            toSave.setId(id);//we set id for article
            toSave.setPharmacy(ap);//we set pharmacy for article (foreign key - should be same as id_article_pharmacy from AricleId)
            System.out.println("ID [Id of pharmacy is: " +toSave.getId().getIdPharmacy() + " | id of article is : "
                    +toSave.getId().getIdArticle() + "] fk pharmacy name is: " + toSave.getPharmacy().getName()); // this is what i get here when i run it : ID [Id of pharmacy is: 1 | id of article is : 1] fk pharmacy name is: Pharmacy BENU - so all data is linked
            //ap.addArticle(toSave);
            articleRepository.save(toSave); //we use repository that extends CrudRepository to save article in db.

    }

当我使用此服务时,出现此错误:java.sql.sqlException:字段“ article_pharmacy_fk”没有认值 在com.MysqL.cj.jdbc.exceptions.sqlError.createsqlException(sqlError.java:129)〜[mysql-connector-java-8.0.21.jar:8.0.21] 在com.MysqL.cj.jdbc.exceptions.sqlError.createsqlException(sqlError.java:97)〜[mysql-connector-java-8.0.21.jar:8.0.21] ......等等 有人可以帮我我尝试过一切吗? :/

..解决方案.... 问题出在我的ArticleId的定义中。我不需要为idPharmacy定义@Column antotation(因为我不想为此创建新列,我想引用它)。所以我删除了@Column注释。我还需要用@MapsId(“ idPharmacy”)替换@MapsId(“ id_article_pharmacy”)。这就是我解决问题的方式。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)