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