使用中间表(中间实体)

时间:2017-08-02 16:31:16

标签: java hibernate jpa hibernate-mapping

我正在尝试使用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”上尝试了以下Mappping

@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=?

(关键部分是选择中的“actionCategory”和“actionType”

这不是我所期望的,Hibernate应该加入。

你知道我做错了吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

经过大量调查,我发现:

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

最后,即使我无法更改数据库,我也可以更改对象模型。

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

如果你有一个表作为2个不同ManyToOne关系的中间实体,也许最好的解决方案是在对象模型中创建中间实体。