jpa:@onetomanyMap和复合主键-未找到逻辑列错误

pieyvz9o  于 2021-06-26  发布在  Java
关注(0)|答案(3)|浏览(381)

我在将一个外键Map到复合主键时遇到问题。我已经尝试过很多解决方案,包括这个帖子@onetomany和composite primary keys?。
所以情况是:
我有两个实体,比方说,box&color,复合主键在子级(color)。

@Entity
@Table(name = "box")
data class Box(
        @Id
        var id: Int = 0,
        ...
       @OneToMany(cascade = [CascadeType.ALL])
        @JoinColumns(
                JoinColumn(name = "box_id", referencedColumnName = "id"),
                JoinColumn(name = "locale", referencedColumnName = "locale"))
        val colors: List<Color> = emptyList(),
)

@Entity
@Table(name = "color")
data class Color(

        @EmbeddedId
        var colorId: ColorId? = null,
) : Serializable

@Embeddable
data class ColorId(
        var id: Int = 0,
        @Column(name = "locale", insertable = false, updatable = false)
        var locale: Locale = Locale.Germany
) : Serializable

所以,在box实体中,我尝试在box和color实体之间创建一个one-omanyMap。为此,我应该使用颜色实体的复合主键吗?如果我尝试将列连接到复合主键(就像我在box实体中所做的那样),我会得到一个错误消息,即-找不到逻辑列“locale”。
我如何解决这个问题?
或者这个问题的最佳解决方案是什么?

0x6upsns

0x6upsns1#

OneToMany Map将连接一个 Box 与许多 Colors . 因此,每个 Color 需要指向一个 Box ,所以每个 Color 具有引用的主键的外键 Box (第页,共页) Int 类型)。

@作为拥有方的一个公司

在Map中,应该使用单个联接列,因为此联接列将放置在 color 表格:

@Entity
@Table(name = "box")
data class Box(
        @Id
        var id: Int = 0,
        ...

        @OneToMany(cascade = [CascadeType.ALL])
        @JoinColumn(name = "box_id", referencedColumnName = "id")
        var colors: MutableList<Color> = mutableListOf()
)

您可以在我的github repo中查看工作示例(kotlin和java)。

@一个单亲作为一个逆(Map)边

数据库透视图 @OneToMany 作为拥有方和 @OneToMany 作为反面(带有一个免费的 @ManyToOne )生成相同的数据库架构-数据库上的外键 color table。这就是为什么 @JoinColumn 注解在这两种情况下看起来都是一样的,不管您将它放在哪一侧—目标是在 many 侧面。

应用前景

“拥有方”的区别在于应用程序的Angular 。jpa/hibernate只从拥有方保存关系。
因此,如果您更改了拥有方,则必须在应用程序代码中设置这一方(属性)。在这种情况下,必须设置 BoxColor ,否则,jpa/hibernate将不会创建关系(即使您添加了 ColorsBox ). 此外,它不会引起任何例外,只是不会建立这种关系。下一次,你会找回你的 Box 从数据库中 Color 列表将为空。
您可以查看工作示例,并在我的github repo中查看所有权的差异。

@Entity
@Table(name = "box")
data class Box(
        @Id
        var id: Int = 0,
        ...

        @OneToMany(cascade = [CascadeType.ALL], mappedBy="box")
        var colors: MutableList<Color> = mutableListOf(),
)

@Entity
@Table(name = "color")
data class Color(

        @EmbeddedId
        var colorId: ColorId? = null,

        // the owning side is changed, therefore you MUST set the box in Color
        // otherwise the relationship in a database will not be saved (!)
        @ManyToOne
        @JoinColumn(name = "box_id")
        var box: Box? = null
) : Serializable

其他可能的问题

因为你和一个 OneToMany 在这个模型中,考虑一些其他可能的问题可能对您很有用。

区域设置不可插入和不可更新

你可能会遇到的另一个问题是储蓄 localeColorId 就像你标记的那样 non-insertable 以及 non-updatable . 如果这是故意的,那就好了(在这种情况下,所有颜色都必须预先插入到数据库中,否则它们将在没有区域设置的情况下插入)。
请记住,在这种情况下,设置locale.german对数据库没有影响。它将被默默地忽略,如果数据库中没有这样的颜色,它将以null插入。

仅指定给一个框的颜色

如果对这种关系进行建模,则只为一个框指定一种颜色(如德语中的黑色)。听起来有点不自然。通常,我会假设黑色可以分配给许多盒子。所以,这将是一个 ManyToMany 关系。再说一次,如果这是故意的,那没关系!

colorid作为主键

这也有点不自然 Locale 作为主键的一部分 Color --德语中的黑色和英语中的黑色是不同的颜色?颜色本身独立于区域设置。颜色的名称取决于区域设置,但更重要的是ui。再说一次,如果这是故意的,那没关系!毕竟,这是你的商业模式!

jdg4fx2g

jdg4fx2g2#

你有两个选择。或者定义一个联接表 @JoinTable(name = "color_box_assignment", joinColumns = ...) 或使用反向Map:

@Entity
@Table(name = "color")
data class Color(

        @EmbeddedId
        var colorId: ColorId? = null,
        @ManyToOne(fetch = LAZY)
        @JoinColumns(
            JoinColumn(name = "box_id", referencedColumnName = "id"),
            JoinColumn(name = "locale", referencedColumnName = "locale"))
        var box: Box? = null
) : Serializable
kpbwa7wx

kpbwa7wx3#

在为您提供解决方案之前,我想向您提供有关 @OneToMany 以及 @JoinColumns 注解。
@OneToMany Map表示这样一个事实,即应用了该Map的实体对另一个实体有许多引用。
i、 东阿 Box 有很多关于 Color(s) 对你来说。
现在要对此进行建模,我建议您反转Map并使用 @ManyToOne 在颜色实体上。

@Entity
@Table(name = "color")
data class Color(

        @EmbeddedId
        var colorId: ColorId? = null,
        @ManyToOne(fetch = LAZY)
        @JoinColumn(name = "box_id"), //referencedColumnName is not needed here as it is inferred as "id"
        var box: Box? = null
) : Serializable

因为外键应该是彩色的。不能将外键从一个框到另一种颜色,因为可能有多种颜色。
另外,请注意它不是 @JoinColumns ,它是单数 @JoinColumn . 如果 Box 实体包含 Composite Primary Key .
话说回来,你们可以一起忽略 @OneToMany Map,因为如果你需要得到一个盒子的所有颜色,在我看来,你可以而且应该使用 Query 应用程序编程接口。
@OneToMany 在这种情况下,Map只是一种方便。但如果你坚持要 @OneToMany Map然后您可以使用以下命令。

@Entity
@Table(name = "box")
data class Box(
        @Id
        var id: Int = 0,
        ...
       @OneToMany(cascade = [CascadeType.ALL], mappedBy="box") // mappedBy will use the "box" reference from the Color Class
        val colors: List<Color> = emptyList(),
)

相关问题