Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.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/xcode/7.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 JPA/Hibernate:Join表上的多个删除关系_Java_Hibernate_Jpa - Fatal编程技术网

Java JPA/Hibernate:Join表上的多个删除关系

Java JPA/Hibernate:Join表上的多个删除关系,java,hibernate,jpa,Java,Hibernate,Jpa,免责声明:这是我的第一个Java项目;边走边学 背景:我继承了一个遗留数据库,在此基础上构建一个新的RESTful API。我们正在使用Spring Boot来提供兼容的服务 参考资料: 问题:我们有一些实体,它们通过联接表彼此之间以及自身之间存在多对多关系。考虑下面的模式: CREATE TABLE ALPHA ( ID VARCHAR(255), NAME VARCHAR(255), CONSTRAINT PK_ALPHA PRIMARY KEY (ID) ); CREATE

免责声明:这是我的第一个Java项目;边走边学

背景:我继承了一个遗留数据库,在此基础上构建一个新的RESTful API。我们正在使用Spring Boot来提供兼容的服务

参考资料:

问题:我们有一些实体,它们通过联接表彼此之间以及自身之间存在多对多关系。考虑下面的模式:

CREATE TABLE ALPHA (
  ID VARCHAR(255),
  NAME VARCHAR(255),
  CONSTRAINT PK_ALPHA PRIMARY KEY (ID)
);

CREATE TABLE BRAVO (
  ID VARCHAR(255),
  NAME VARCHAR(255),
  CONSTRAINT PK_BRAVO PRIMARY KEY (ID)
);

CREATE TABLE RELATIONSHIP (
  ID INT AUTO_INCREMENT,
  FROM_ID VARCHAR(255),
  TO_ID VARCHAR(255)
);
其中,资源实体建模如下:

public class Alpha implements Serializable {

    private String id;
    private String name;
    private Set<Alpha> alphas = new HashSet<>();
    private Set<Bravo> bravos = new HashSet<>();

    @Id
    @Column(name = "ID", unique = true, nullable = false)
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid")
    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinTable(
            name = "RELATIONSHIP",
            joinColumns = @JoinColumn(name = "FROM_ID"),
            inverseJoinColumns = @JoinColumn(name = "TO_ID")
    )
    public Set<Alpha> getAlphas() {
        return alphas;
    }

    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinTable(
            name = "RELATIONSHIP",
            joinColumns = @JoinColumn(name = "FROM_ID"),
            inverseJoinColumns = @JoinColumn(name = "TO_ID")
    )
    public Set<Bravo> getBravos() {
        return bravos;
    }

}
现在让我们假设我们有一个
Alpha
记录
A1
,它与
A2
A3
B1
B2
有关。首先,我们删除与
A2
的关系

从我们的API来看,这将是对
http://localhost:9000/api/alphas/a1/relationships/alphas
带车身

{
  "data": [
    {
      "type": "alphas", 
      "id": "a2" 
    }
  ]
}
幕后Hibernates执行我期望的操作,并生成以下SQL查询:

2018-07-13 09:48:23.687 DEBUG 7964 --- [nio-9000-exec-5] org.hibernate.SQL                        : 
Hibernate: 
    select
        alpha0_.id as id1_0_,
        alpha0_.name as name2_0_ 
    from
        alpha alpha0_ 
    where
        alpha0_.id in (
            ?
        )
2018-07-13 09:48:23.688 TRACE 7964 --- [nio-9000-exec-5] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [a1]
2018-07-13 09:48:23.690 DEBUG 7964 --- [nio-9000-exec-5] org.hibernate.SQL                        : 
Hibernate: 
    select
        alphas0_.from_id as from_id2_2_0_,
        alphas0_.to_id as to_id3_2_0_,
        alpha1_.id as id1_0_1_,
        alpha1_.name as name2_0_1_ 
    from
        relationship alphas0_ 
    inner join
        alpha alpha1_ 
            on alphas0_.to_id=alpha1_.id 
    where
        alphas0_.from_id=?
2018-07-13 09:48:23.690 TRACE 7964 --- [nio-9000-exec-5] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [a1]
2018-07-13 09:48:23.699 DEBUG 7964 --- [nio-9000-exec-5] org.hibernate.SQL                        : 
Hibernate: 
    select
        alpha0_.id as id1_0_,
        alpha0_.name as name2_0_ 
    from
        alpha alpha0_ 
    where
        alpha0_.id in (
            ?
        )
2018-07-13 09:48:23.699 TRACE 7964 --- [nio-9000-exec-5] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [a2]
2018-07-13 09:48:23.721 DEBUG 7964 --- [nio-9000-exec-5] org.hibernate.SQL                        : 
Hibernate: 
    delete 
    from
        relationship 
    where
        from_id=? 
        and to_id=?
2018-07-13 09:48:23.722 TRACE 7964 --- [nio-9000-exec-5] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [a1]
2018-07-13 09:48:23.724 TRACE 7964 --- [nio-9000-exec-5] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [VARCHAR] - [a2]
关键部分是
从关系中删除,其中from_id=?和to_id=?

现在,当尝试删除第二个
Alpha
关系
A3
时,问题出现了,在这个关系中,Hibernate执行几乎完全相同的顺序,除了
delete
查询忽略了
和to_id=?
,即

Hibernate: 
    delete 
    from
        relationship 
    where
        from_id=?
其意外后果是删除表中所有其他
A1
关系,即
B1
B2

这就是我问题的症结所在。Hibernate似乎只看到了另一条相关的
Alpha
记录,因此决定通过省略
和to_id
语句来简化查询

我可能错过了一些非常明显的东西


我还应该指出,我曾试图在
关系表上使用复合键,但没有成功。

这是一个不寻常的设计,我怀疑这会让人混淆
休眠
。在多个
Many-to-Many
关系之间共享一个连接表不是好的数据库设计,因为它不能具有任何外键/引用完整性

其次,
Hibernate
管理关系,因此可以控制
@JoinTable
,我不知道它将如何处理使用同一个表映射的多个实体关系。显然,不是很好


最简单的解决方案(如果可以的话)是有两个映射表。一个用于
Alpha-Alpha
之间的关系,另一个用于
Alpha-Bravo

之间的关系,并避免将关系表映射为实体,因为它已经映射为联接表。我完全同意。将关系映射到实体之后通常是在
Hibernate
@StuPointerException之外对关系进行微观管理的代码。我完全同意你的看法,整个数据库设计一团糟,我认为,需要尽快取消!不幸的是,这正是我现在要面对的。我想可能是我缺乏JPA/Hibernate方面的经验造成的,但是如果大家一致认为这不能很好地完成,那么我会给出我的答案。@jdub我感觉到了你的痛苦。我看不出你的
Hibernate
注释有什么问题。如果有什么安慰的话,我不认为将联接表拆分为2应该是一项非常大/危险的任务。尽管如此,如果数据库的其余部分遵循类似的“模式”,这可能不是要克服的最后一个障碍。祝你好运
Hibernate: 
    delete 
    from
        relationship 
    where
        from_id=?