Spring Boot Hibernate 将数据插入 Postgres 中的错误列

Posted

技术标签:

【中文标题】Spring Boot Hibernate 将数据插入 Postgres 中的错误列【英文标题】:Spring Boot Hibernate inserts Data into wrong Columns in Postgres 【发布时间】:2022-01-17 14:51:13 【问题描述】:

初始情况: 我有这两个实体,GroceriesList 和 Product。

杂货清单: 一个 GroceriesList 可以有多个产品。

@Entity
@Table(name = "lists")
public class GroceriesList 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "list_id")
    private Long listId;

    @Column(name = "list_name")
    private String listName;


    @ManyToMany(cascade = CascadeType.MERGE)
    @JoinTable(name = "lists_products",
            joinColumns = @JoinColumn(name = "product_id", referencedColumnName = "list_id"),
            inverseJoinColumns = @JoinColumn(name = "list_id", referencedColumnName = "product_id")
    )
    private Set<Product> products;


产品: 一个产品可以分配到多个 GroceriesLists

@Entity
@Table(name = "products")
public class Product 

    public enum Category 
        Dairy,
        Fruit,
        Vegetable,
        Meat,
        Grains
    

    // Product ID Column, GenerationType.Identity refers to auto incr in Postgres
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "product_id")
    private Long productId;

    @Column(name = "product_name")
    private String productName;

    @Column(name = "product_vendor")
    private String productVendor;

    @Enumerated(EnumType.STRING)
    @Column(name = "product_category")
    private Category productCategory;

    @Column(name = "product_storedquantity")
    private Integer productStoredQuantity;

    @JsonIgnore
    @ManyToMany(mappedBy = "products")
    private List<GroceriesList> groceriesLists;

实体和关系存储在 Postgres 的三个不同表中(一个用于列表,一个用于产品,一个用于关系映射表)。

映射表: Mapping Table "lists_products"

产品示例: Sample Product with Id=4

问题:我正在尝试创建新列表,并且可以。但是,您可以从映射表图像中发现,Hibernate 将 ID 插入到错误的列中。映射表中的list_id当前正在获取product_id,映射表中的product_id正在获取list_id。 我试图更改 GroceriesList 实体中 @JoinTable 注释中列名和引用的顺序。但是,这会引发映射错误。我认为我的错误在于该注释中的某个地方。有趣的是,Hibernate 使用了正确的SQL-Query。我在这里错过了什么?

【问题讨论】:

【参考方案1】:

在咨询了 fladdimir 的解决方案后,它给了我一个想法,我解决了我的问题。问题出在@JoinColumn 注释中,我认为“name = ...”属性是指数据库中的列名。

@ManyToMany(cascade = CascadeType.MERGE)
@JoinTable(name = "lists_products",
        joinColumns = @JoinColumn(name = "product_id", referencedColumnName = "list_id"),
        inverseJoinColumns = @JoinColumn(name = "list_id", referencedColumnName = "product_id")
)
private Set<Product> products;

但是,该属性是指Spring Boot中Entity内部声明的变量,即listId

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "list_id")
private Long listId;

因此,@JoinTable 注解的工作实现应如下所示,其中“name = ...”使用该变量名:

@ManyToMany(cascade = CascadeType.MERGE)
@JoinTable(name = "lists_products",
        joinColumns = @JoinColumn(name = "listId", referencedColumnName = "list_id"),
        inverseJoinColumns = @JoinColumn(name = "productId", referencedColumnName = "product_id")
)
private Set<Product> products;

【讨论】:

@JoinColumn中的name是DB中外键列的名称,不需要与任何实体类属性docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/…相同 那么很奇怪我的解决方案是有效的。会不会是hibernate在“list”和“Id”之间插入下划线并将“listId”中的“I”小写?就像我提到的那样,您的解决方案不起作用,因为 postgres 会引发无法识别的列错误。 您尝试过使用新数据库吗? (否则您当然需要重命名列) 不,我使用了我已经创建的一个数据库。但我会尝试使用新数据库,看看会发生什么。非常感谢您的帮助,非常感谢!【参考方案2】:

@JoinTable 中有错字,@JoinColumn 名称应在其引用的实体之后选择以避免混淆:

@ManyToMany(cascade = CascadeType.MERGE)
@JoinTable(name = "lists_products",
        joinColumns = @JoinColumn(name = "list", // <- not "product"
           referencedColumnName = "list_id"),
        inverseJoinColumns = @JoinColumn(name = "product", // <- not "list"
           referencedColumnName = "product_id")
)
private Set<Product> products;

In which case do you use the JPA @JoinTable annotation?https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/JoinTable.html

【讨论】:

嘿,谢谢你帮助我!不幸的是,您的意见并没有解决我的问题。但是,它给了我一个想法,我可以解决我的问题!问题是,“名称”需要引用变量名,即“productId”和“listId”,而不是我假设的表名

以上是关于Spring Boot Hibernate 将数据插入 Postgres 中的错误列的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot Hibernate 将数据插入 Postgres 中的错误列

Hibernate 和 CRUDRepository Spring Boot

Hibernate 两次将数据插入到 Join Table 中,导致 Spring Boot 项目中出现“ORA-00001:违反唯一约束”

无法从 Spring Boot REST 中的 Hibernate POJO 返回 JSON

Spring Boot 未使用 Spring Data 和 Hibernate 与 sql Server 一起运行

Spring Boot Batch 中的 Hibernate_sequence 错误(预定)