【问题标题】:JPA ManyToMany fails with "must have same number of columns as the referenced primary key"JPA ManyToMany 失败,“列数必须与引用的主键相同”
【发布时间】:2021-12-20 10:40:54
【问题描述】:

我有三个表customerproductsalessales 是存储客户产品的连接表,如下图所示: customer, product and Sales tables

我的实体定义如下:

客户.java

@Entity
@Table(name="customer")
public class Customer {
    @Id
    @Column(name="c_id")
    private String customerId;
    
    @Column(name="customer_name")
    private String customerName;
    
    @ManyToMany
    @JoinTable(
            name = "sale",
            joinColumns = @JoinColumn(name = "c_id"),
            inverseJoinColumns = @JoinColumn(name = "p_id"))
    private Set<Product> customerProducts = new HashSet<>();
}

Product.java

@Entity
@Table(name="product")
public class Product {
    @Id
    @Column(name="p_id")
    private String productId;
    
    @Column(name="product_name")
    private String productName;
    
    @Column(name="price")
    private Double price;

    // ... Setters & Getters
}

Sales.java

@Entity
@Table(name="sales")
public class Sales {
    @EmbeddedId
    private SalesPK salesId;
    
    @Column(name="qty")
    private Long qty;

    // ... Setters & Getters
}

SalesPK.java

@Embeddable
public class SalesPK implements Serializable {
    @Column(name = "c_id")
    private String customerId;
    @Column(name = "p_id")
    private String productId;
    public SalesPK() {}

    public SalesPK(String customerId, String productId) {
        this.customerId = customerId;
        this.productId = productId;
    }
}

CustomerRepository.java

@Repository
public interface CustomerRepository extends CrudRepository<Customer, String> {
    @Query("select customer from Customer customer " +
            "left join fetch customer.customerProducts " +
            "where customer.customerName = :customerName")
    public Customer getCustomerPurchasedProducts(String customerName);
}

我的 Spring Boot 应用程序无法启动并出现以下异常:

org.hibernate.MappingException: 外键 (FK7wwx8x75009xqb1y0tawm8rty:SALES [p_id])) 必须有相同数量的 列作为引用的主键 (SALES [c_id,p_id])

我在这里缺少什么?我已按照https://www.baeldung.com/jpa-many-to-many

中所述的说明进行操作

更新:

上述解决方案没有问题,我在@ManyToMany 声明中拼错了“sales”表,从“sale”更改为“sales”解决了这个问题。奇怪的行为,为什么它没有对丢失的表进行编译,而是抱怨实际的复合主键定义。

以下代码修复了问题:

    @ManyToMany
    @JoinTable(
            name = "sales",
            joinColumns = @JoinColumn(name = "c_id"),
            inverseJoinColumns = @JoinColumn(name = "p_id"))
    private Set<Product> customerProducts = new HashSet<>();
}

【问题讨论】:

    标签: spring-boot hibernate jpa spring-data-jpa spring-data


    【解决方案1】:

    我会对这些类进行一些不同的映射:

    @Entity
    @Table(name="customer")
    public class Customer {
        @Id
        @Column(name="c_id")
        private String customerId;
        
        @Column(name="customer_name")
        private String customerName;
        
        @OneToMany(mappedBy = "customer")
        private Set<Sale> customerSales = new HashSet<>();
    }
    
    
    @Entity
    @Table(name="product")
    public class Product {
        @Id
        @Column(name="p_id")
        private String productId;
        
        @Column(name="product_name")
        private String productName;
        
        @Column(name="price")
        private Double price;
    }
    
    
    @Entity
    @Table(name="sales")
    public class Sales {
        @EmbeddedId
        private SalesPK salesId;
        
        @MapsId("customerId") // maps customerId attribute of embedded id
        @ManyToOne
        Customer customer;
        
        @MapsId("productId") // maps productId attribute of embedded id
        @ManyToOne
        Product product;
        
        @Column(name="qty")
        private Long qty;
    
        // ... Setters & Getters
    }
    
    
    @Embeddable
    public class SalesPK implements Serializable {
        @Column(name = "c_id")
        private String customerId;
    
        @Column(name = "p_id")
        private String productId;
    
        public SalesPK() {}
    
        public SalesPK(String customerId, String productId) {
            this.customerId = customerId;
            this.productId = productId;
        }
    }
    

    【讨论】:

    • 如何获得产品名称? customerSales 仅包含产品 ID,但不包含产品名称。
    • 顺便说一句,当我按照你的映射时,我得到了同样的错误,
    • 你确定你正在准确地映射它们在答案中的样子吗?因为customerSales 应该包含Sales 的实例,并且每个Sales 应该包含Product 的实例,当然,每个Product 都会有它的productName
    • hibernate 有一个错字并且没有误导性的异常,我已经更新了我的答案。
    猜你喜欢
    • 2020-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-18
    • 1970-01-01
    • 2019-11-18
    • 1970-01-01
    • 2014-07-27
    相关资源
    最近更新 更多