Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Hibernate使用JoinTable为可选的双向OneToOne生成错误查询_Java_Mysql_Hibernate_Jpa_Hibernate Mapping - Fatal编程技术网

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表示解析后的消息
TagDetail可能与RawDeviceMessage关联,也可能与RawDeviceMessage无关,因为它可以直接创建,而无需解析原始消息。因此,我在RawDeviceMessage和TagDetail之间有一个可选的双向OneToOne关系

在数据库中,我有以下表格:

  • 原始设备消息(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关系
我已经像这样映射了我的Java类:

RawDeviceMessage 标记细节
问题

我的问题是,在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的JpaRepository
List 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