【发布时间】:2016-10-27 06:29:37
【问题描述】:
我有两个实体:
- RawDeviceMessage,表示来自设备的原始消息
- TagDetail 表示解析后的消息
TagDetail 可能会或可能不会与 RawDeviceMessage 相关联,因为它可以直接创建而无需解析原始消息。因此,我在 RawDeviceMessage 和 TagDetail 之间有一个可选的双向 OneToOne 关系。
在数据库中我有以下表格:
- raw_device_message(id + 其他列)
- tag_detail(id + 其他列)
- tag_detail_has_raw_device_message (tag_detail_id , raw_device_message_id) :此表是一个 JoinTable,具有适当的 SQL 约束和外键以在数据库级别强制执行 OneToOne 关系.
我已经像这样映射了我的 Java 类:
原始设备消息
@Entity
@Table(name = "raw_device_message")
public class RawDeviceMessage implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", unique = true, updatable = false, nullable = false)
private Long id;
@OneToOne(mappedBy = "rawDeviceMessage", fetch = FetchType.LAZY)
private TagDetail tagDetail;
public RawDeviceMessage(){}
public Long getId(){...}
public void setId(final Long id){...}
public TagDetail getTagDetail(){...}
public RawDeviceMessage setTagDetail(TagDetail tagDetail){...}
}
标签详情
@Entity
@Table(name = "tag_detail")
public class TagDetail implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", unique = true, updatable = false, nullable = false)
private Long id;
@OneToOne(fetch = FetchType.EAGER, cascade = { CascadeType.REFRESH, CascadeType.MERGE })
@JoinTable(
name="tag_detail_has_raw_device_message",
joinColumns=@JoinColumn(name="tag_detail_id"),
inverseJoinColumns=@JoinColumn(name="raw_device_message_id"))
private RawDeviceMessage rawDeviceMessage;
public TagDetail() {}
public Long getId(){...}
public void setId(final Long id){...}
public RawDeviceMessage getRawDeviceMessage(){...}
public void setRawDeviceMessage(RawDeviceMessage rawDeviceMessage){...}
}
问题
我的问题是,在 RawDeviceMessage 资源上执行 find all 时,Hibernate 会生成错误的 SQL 查询:
SELECT rawdevicem0_.id AS id1_15_,
rawdevicem0_2_.tag_detail_id AS tag_deta0_37_,
FROM raw_device_message rawdevicem0_
LEFT OUTER JOIN tag_detail_has_raw_device_message rawdevicem0_2_ ON rawdevicem0_.id=rawdevicem0_2_.tag_detail_id
CROSS JOIN tag_detail tagdetail1_
LEFT OUTER JOIN tag_detail_has_raw_device_message tagdetail1_1_ ON tagdetail1_.id=tagdetail1_1_.tag_detail_id
WHERE rawdevicem0_2_.tag_detail_id=tagdetail1_.id
ORDER BY rawdevicem0_.id ASC
如您所见,在第一个LEFT OUTER JOIN中,连接条件为rawdevicem0_.id=rawdevicem0_2_.tag_detail_id
它试图将 raw_device_message.id 与 tag_detail_has_raw_device_message.tag_detail_id 连接起来,这没有任何意义,并且会弄乱所有结果。
连接条件应该是rawdevicem0_.id=rawdevicem0_2_.raw_device_message_id
此条件将正确地将 raw_device_message.id 与 tag_detail_has_raw_device_message.raw_device_message_id 连接起来
我已经缩短了hibernate生成的查询以删除所有不相关的字段,但是在生成的查询中没有raw_device_message_id列,所以肯定有问题。
这是休眠错误还是我的映射错误?
【问题讨论】:
-
请发布您的
findAll查询,乍一看我会说您在那里做错了。 -
@DraganBozanovic 我正在使用 Spring 的 JpaRepository
List<T> findAll();所以我自己不写任何查询。 -
你使用的是什么版本的休眠?你用的是什么数据库?我将您的实体复制到 postgres 数据库中并告诉它自动导出模式。对我来说,FK 是在数据库中正确创建的,并且生成的查询也可以按预期工作。我无法重现您所描述的行为。
-
我使用的是 Hibernate 5.1.0.Final 和 MySQL 5.7。我不知道为什么我有这个错误。我最终删除了从 RawDeviceMessage 到 TagDetail 的双向关系以“解决”我的问题。
标签: java mysql hibernate jpa hibernate-mapping