【问题标题】:JPA mapping with two ManyToOne using an intermediary table (middle entity)使用中间表(中间实体)与两个 ManyToOne 进行 JPA 映射
【发布时间】:2017-08-02 16:31:15
【问题描述】:

我正在尝试使用 JoinTable 设置 JPA 映射,当 Hibernate(我的 JPA 实现)进行查询时,它似乎被忽略了。

解释用例

每次用户获取我的应用程序的页面时,我都会在 USAGE_LOG 表中插入一行(带有用户的 id 和页面的 id)。

每个页面都与一个类别(例如:设置、订单、项目、新闻...)和类型(例如创建、更新、显示、删除)相关。

所以,我有某种中间实体表,它将页面链接到:类别 + 类型。就像一个三元组:(页面、类别、类型)

我的表结构

table USAGE_LOG (for information only, this one works well)
   ID PrimaryKey
   USER_ID Foreign key to column ID of table USER
   USAGE_LOG_PAGE_ID Foreign key to column ID of table USER_LOG_PAGE

table USAGE_LOG_PAGE
   ID PrimaryKey
   URL VARCHAR
   USER_ACTION_ID Foreign key to column ID of table USER_ACTION

table USER_ACTION
   ID PrimaryKey
   ACTION_CATEGORY_ID Foreign key to column ID of table ACTION_CATEGORY
   ACTION_TYPE_ID Foreign key to column ID of table ACTION_CATEGORY

table ACTION_CATEGORY
   ID PrimaryKey
   NAME VARCHAR

table ACTION_TYPE
   ID PrimaryKey
   NAME VARCHAR

所以 USER_ACTION 表是一个连接表,其特殊性在于它同时将一个 USAGE_LOG_PAGE 链接到一个 ACTION_CATEGORY 和一个 ACTION_TYPE。

另外,我可以将多个 USAGE_LOG_PAGE 链接到相同的 ACTION_CATEGORY 和 ACTION_TYPE。

很遗憾,我无法更改数据库结构(它是遗留代码)。

我在实体“UsageLogPage”上尝试了以下映射

@ManyToOne
@JoinTable(name="action",
        joinColumns=@JoinColumn(name="ID", referencedColumnName="USER_ACTION_ID"),
        inverseJoinColumns=@JoinColumn(name="ACTION_CATEGORY_ID", referencedColumnName="ID"))
@Getter @Setter
private ActionCategory actionCategory;

@ManyToOne
@JoinTable(name="action",
    joinColumns=@JoinColumn(name="ID", referencedColumnName="USER_ACTION_ID"),
    inverseJoinColumns=@JoinColumn(name="ACTION_TYPE_ID", referencedColumnName="ID"))
@Getter @Setter
private ActionType actionType;

(我将 Lombok 用于 @Getter 和 @Setter)

此映射可以编译,但是当我尝试获取数据时,出现以下异常: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:“字段列表”中的未知列“usagelogpa0_.actionCategory”

确实,Hibernate 查询是:

select usagelogpa0_.ID as ID1_80_0_,
   usagelogpa0_.actionCategory as actionCa2_80_0_,
   usagelogpa0_.actionType as actionTy3_80_0_,
   usagelogpa0_.URL as URL5_80_0_
from usage_log_page usagelogpa0_
where usagelogpa0_.ID=?

(关键部分是select中的“actionCategory”和“actionType”)

这不是我所期望的,Hibernate 应该做一个连接。

你知道我做错了什么吗?

谢谢!

【问题讨论】:

    标签: java hibernate jpa hibernate-mapping


    【解决方案1】:

    经过大量调查,我发现:

    • 它没有按预期工作,因为我将@ManyToOne 和@JoinTable 注释放在属性级别。我手动创建了一个 getter 并将注释放在上面,它们被考虑在内
    • 它仍然不能正常工作,因为 Hibernate 在运行时没有在 USAGE_LOG_PAGE 表上找到列“USER_ACTION_ID”。由于某种原因(我找不到),此列不在可用字段中。在实体“UsageLogPage”中添加字段“usage_action_id”时,它找到了该属性,但拒绝创建映射,因为USAGE_ACTION_ID不是主键。

    最后,即使我不能改变数据库,我也可以改变对象模型。

    所以我创建了中间实体“UserAction”,将其与 UsageLogPage 实体上的 ManyToOne 绑定,从 UsageLogPage 中移除属性“actionCategory”和“actionType”,并将它们作为 ManyToOne 添加到新的 UserAction 实体中。

    如果您有一个表充当 2 个不同的多对一关系的中间实体,那么最好的解决方案可能是在您的对象模型中创建中间实体。

    【讨论】:

      猜你喜欢
      • 2020-11-05
      • 2016-07-05
      • 1970-01-01
      • 2012-11-28
      • 1970-01-01
      • 1970-01-01
      • 2015-10-03
      • 1970-01-01
      • 2011-07-13
      相关资源
      最近更新 更多