Java Hibernate使用JoinTable为可选的双向OneToOne生成错误查询
我有两个实体:Java Hibernate使用JoinTable为可选的双向OneToOne生成错误查询,java,mysql,hibernate,jpa,hibernate-mapping,Java,Mysql,Hibernate,Jpa,Hibernate Mapping,我有两个实体: RawDeviceMessage表示来自设备的原始消息 TagDetail表示解析后的消息 TagDetail可能与RawDeviceMessage关联,也可能与RawDeviceMessage无关,因为它可以直接创建,而无需解析原始消息。因此,我在RawDeviceMessage和TagDetail之间有一个可选的双向OneToOne关系 在数据库中,我有以下表格: 原始设备消息(id+其他列) 标记详细信息(id+其他列) tag\u detail\u具有\u raw\
- RawDeviceMessage表示来自设备的原始消息
- TagDetail表示解析后的消息
- 原始设备消息(id+其他列)
- 标记详细信息(id+其他列)
- tag\u detail\u具有\u raw\u device\u message(tag\u detail\u id,raw\u device\u message\u id):此表是一个具有适当SQL约束和外键的连接表,用于在数据库级别强制执行OneToOne关系
问题 我的问题是,在RawDeviceMessage资源上执行“全部查找”时,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
如您所见,在第一个左外部联接中
,联接条件是rawdevicem0\uu2.id=rawdevicem0\u2.tag\u detail\u id
它试图将raw\u device\u message.id
与tag\u detail\u连接起来。tag\u detail\u id
,这毫无意义,并且会将所有结果弄乱
相反,连接条件应该是,rawdevicem0\uu0.id=rawdevicem0\u2\u0.raw\u设备\u消息\u id
此条件将正确地将raw\u device\u message.id
与tag\u detail\u连接起来。raw\u device\u message\u id
我缩短了hibernate生成的查询以删除所有不相关的字段,但是在生成的查询中没有列raw\u device\u message\u id
,因此肯定是出了问题
这是一个hibernate错误还是我的映射错误?如果标记详细信息的目的是将原始设备消息表链接到两个表,那么您可以删除它。你只需要两张桌子就可以一对一了。 更多详情请参阅- 但是,如果您希望有一个中间映射表,因为它有一些关于该关系的附加信息,那么请在此处提供更多详细信息
我需要一个联接表,因为我的OneToOne关联是可选的。我不想让tag_detail表中的一列填充一半的空值。我已经阅读了你第二个链接中的文档。在“您可以将可选的一对一关联映射到带有注释的中间联接表”这句话下面,正好是我正在使用的映射。但是,正如我发现的,它不起作用,因为生成的SQL是错误的。是的。但该示例没有描述另一方(项目到装运项目的映射,它只显示了装运项目到装运项目的映射)。另外,我很好奇您是如何得到这个SQL的,因为RawDeviceMessage延迟加载TagDevice,所以当我尝试使用findAll()编写相同的代码时,我得到了一个更简单的SQL。实体映射/类是否正确?我刚刚将hibernate日志设置为trace,并生成了sql。Hibernated获取了关系,因为我正在JPA标准规范中访问它。请发布您的
findAll
查询,乍一看,我会说您做错了。@DraganBozanovic我在使用Spring的JpaRepositoryList findAll()代码>所以我自己不写任何查询。您使用的是什么版本的hibernate?你用的是什么数据库?我将您的实体复制到postgres DB中,并告诉它自动导出模式。对我来说,FK是在数据库中正确创建的,生成的查询也按预期工作。我无法重现您描述的行为。我正在使用Hibernate 5.1.0.Final和MySQL 5.7。我不知道我为什么会有这个错误。最后,我删除了从RawDeviceMessage到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){...}
}
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