Search code examples
springjpakotlinhibernate-mapping

One-To-Many Foreign key must have same number of columns as the referenced primary key


I am trying to implement a one to many association between an order and orderproduct and I am always encountering this exception:

Foreign key (FKmn6eaqdlnl33lnryjkwu09r0m:order_product_entity [order_id,product_id])) must have same number of columns as the referenced primary key (orders [id])

I know what it means but I´m not sure how I should change my scheme to solve it. My design is based on this tutorial : Spring Java eCommerce Tutorial

I can´t tell the difference except my code is written in Kotlin.

I am using Spring Boot with Spring Data JPA and Kotlin.

My Product Entity:

@Entity
@Table(name = "product")
data class ProductEntity(
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        var id: Long,
        @NotNull(message = "Product name is required")
        var name: String,
        var price: Double,
        var description: String

)

My Order Entity:

@Entity
@Table(name = "orders")
data class OrderEntity(
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        var id:Long,

        var dateCreated:Date,

        var status:String,

        @JsonManagedReference
        @OneToMany(cascade = arrayOf(CascadeType.ALL), mappedBy = "orderProductEntityId")
        @Valid
        val orderProducts: List<OrderProductEntity>
)

OrderProductEntity:

@Entity
data class OrderProductEntity(
        @EmbeddedId
        @JsonIgnore
        var orderProductEntityId: OrderProductEntityId,

        @JsonBackReference
        @ManyToOne(optional = false, fetch = FetchType.LAZY)
        var order: OrderEntity,

        @ManyToOne(optional = false, fetch = FetchType.LAZY)
        var product: ProductEntity,

        @Column(nullable = false)
        var quantity: Int = 0
)

My composite primary key:

@Embeddable
data class OrderProductEntityId(
        @Column(name = "order_id")
        var orderId: Long = 0,

        @Column(name = "product_id")
        var productId: Long = 0
) : Serializable

Any suggestions?


Solution

  • I believe you are using "derived identities". Try mapping OrderProductEntity like this:

    @Entity
    data class OrderProductEntity(
        @EmbeddedId
        @JsonIgnore
        var orderProductEntityId: OrderProductEntityId,
    
        @JsonBackReference
        @ManyToOne(optional = false, fetch = FetchType.LAZY)
        @MapsId("orderId") // maps orderId attribute of embedded id
        var order: OrderEntity,
    
        @ManyToOne(optional = false, fetch = FetchType.LAZY)
        @MapsId("productId") // maps productId attribute of embedded id
        var product: ProductEntity,
    
        @Column(nullable = false)
        var quantity: Int = 0
    )
    

    Note the new @MapsId annotations.

    Derived identities are discussed (with examples) in the JPA 2.2 spec in section 2.4.1.