Java 返回没有父实体的实体?

Java 返回没有父实体的实体?,java,sql,jpa,Java,Sql,Jpa,我有一个在图形中使用的类,因此可以有父类和子类: @Entity(name=“教学需求”) @表(name=“教学需求”) 公共类EducationalNeedEntity扩展AbstractEntity实现EducationalNeed{ 私有字符串名称; 私有字符串描述; @ManyToMany(targetEntity=EducationalNeedEntity.class,fetch=FetchType.LAZY) 私有集父项=新哈希集(0); @ManyToMany(targetEnt

我有一个在图形中使用的类,因此可以有父类和子类:

@Entity(name=“教学需求”)
@表(name=“教学需求”)
公共类EducationalNeedEntity扩展AbstractEntity实现EducationalNeed{
私有字符串名称;
私有字符串描述;
@ManyToMany(targetEntity=EducationalNeedEntity.class,fetch=FetchType.LAZY)
私有集父项=新哈希集(0);
@ManyToMany(targetEntity=EducationalNeedEntity.class,fetch=FetchType.LAZY)
私有集子项=新哈希集(0);
...
}
超类
AbstractEntity
用于定义
@Id
字段:

@MappedSuperclass
公共抽象类AbstractEntity实现了可序列化{
...
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私人长id;
...
}
我有以下请求,它应该返回“parents”集合为空的实体

@Query(“从教学需要pn中选择pn,其中pn.parents为空”)
Iterable findRoots();
我的问题是,当执行此请求时,我得到以下“非空约束冲突”:

问题:如何返回没有父实体的实体


更新:生成的架构如下所示:

CREATE MEMORY TABLE PUBLIC.PEDAGOGICALNEED(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) NOT NULL PRIMARY KEY,DESCRIPTION VARCHAR(255),NAME VARCHAR(255))
ALTER TABLE PUBLIC.PEDAGOGICALNEED ALTER COLUMN ID RESTART WITH 1
CREATE MEMORY TABLE PUBLIC.PEDAGOGICALNEED_PEDAGOGICALNEED(
    PEDAGOGICALNEED_ID BIGINT NOT NULL,
    PARENTS_ID BIGINT NOT NULL,
    CHILDREN_ID BIGINT NOT NULL,
    PRIMARY KEY(PEDAGOGICALNEED_ID,CHILDREN_ID),
    CONSTRAINT FK_GSX50JH17YMGUMDQ7ADD0Y0Y5 FOREIGN KEY(PARENTS_ID) REFERENCES PUBLIC.PEDAGOGICALNEED(ID),
    CONSTRAINT FK_L6QY3L7AMTRVX1O62WVS6C9X8 FOREIGN KEY(PEDAGOGICALNEED_ID) REFERENCES PUBLIC.PEDAGOGICALNEED(ID),
    CONSTRAINT FK_EHV0QET4GVHBX733YJV6Q9KQD FOREIGN KEY(CHILDREN_ID) REFERENCES PUBLIC.PEDAGOGICALNEED(ID))
我不理解这个映射,为什么只有一个表“EducationalNeed\u EducationalNeed”和三个字段?教育需求实体与其父母之间的联系与同一实体与其子女之间的联系无关。因此,应该有两个表,而不是只有一个表,每个表只有两列:

  • 第一个表应该有(教学需求ID,儿童ID)作为键
  • 第二个表应该有(教学需求ID、家长ID)作为键

    • 这不是由查询引起的异常。它必须是在查询之前触发的持久化操作的异常

      在执行查询之前,持久性提供程序必须刷新所有dml语句

      列EducationalNeed_ID在th DB上不能为null,但您没有为该列提供值


      查询看起来很好。

      您的数据库表
      educationalneed\u educationalneed
      对于介于
      educationalneedentity
      s之间的多对多属性,有一列
      educationalneed\u ID

      在EducationalNeedEntity中为这样的ID列提供列定义(伪代码):

      您可以自己提供id(在持久化实体之前),也可以使用生成的id值

      重要:为避免冗余,不应在两种关系上使用
      @JoinTable
      。在一个关系上使用
      @JoinTable
      ,在另一个关系上使用
      mappedBy

      一个简单的示例,展示了如何创建这样一个“节点网络”(使用Hibernate 4.3.8和Derby 10.9.1.0进行了测试):

      @实体
      公共类节点{
      @身份证
      公共int id;
      公共字符串节点名;
      @许多
      @JoinTable(name=“关系”)
      公开家长名单;
      @许多(mappedBy=“父母”)
      公开儿童名单;
      公共静态void main(字符串[]args){
      EntityManagerFactory EntityManagerFactory=Persistence.createEntityManagerFactory(“persistenceUnit”);
      EntityManager EntityManager=EntityManager工厂。createEntityManager();
      EntityTransaction=entityManager.getTransaction();
      transaction.begin();
      persist(新节点());
      commit();
      entityManager.close();
      }
      }
      
      这将创建两个表:

      • 表节点
        • 列ID(int)
        • 列节点名(varchar(255)可为空)
      • 表关系
        • 列父项ID(int)
        • 列子项ID(int)

      更新:这不起作用,请参阅最佳答案以了解如何获取单个联接表


      问题解决了!我只需要使用以下命令指定“联接表”的名称:

      @ManyToMany(targetEntity=EducationalNeedEntity.class,fetch=FetchType.LAZY)
      @JoinTable(name=“教育需求家长”)
      私有集父项=新哈希集(0);
      @ManyToMany(targetEntity=EducationalNeedEntity.class,fetch=FetchType.LAZY)
      @JoinTable(name=“EducationalNeed_children”)
      私有集子项=新哈希集(0);
      

      谢谢你的帮助

      抽象实体(超类)中定义的
      @Id
      字段。我将更新我的问题。@geceo您能尝试使用
      策略=生成类型.IDENTITY
      (只是一个猜测)我很高兴您提醒我我的错误,您完全正确地认识到我使用两次
      @JoinTable
      引入冗余的事实。我现在对映射的工作方式有了更好的理解。谢谢!我很困惑,我以为您想要一个映射表并将父关系存储在那里。然后可以根据该数据计算子关系。否则,数据库中会有大量冗余。考虑在你的孩子中使用<代码> MaPdBue<代码> -关系而不是<代码>可联合的< /代码>。是的,我想你是对的,我引入了冗余。关于您的建议,我在children关系中尝试了“mappedBy”,但它生成了一个包含三列(EducationalNeed\u ID、Parent\u ID、Child\u ID)的中间表,在这个表中我想不出任何有意义的三元组。因此,使用
      @JoinTable
      似乎是只获得2列的唯一方法。如果你知道如何避免冗余,我很感兴趣。我更新了我的答案,以包含一个测试示例,该示例具有双向多个关系,但只有一个中间表。谢谢你,我将在我的项目再次编译后立即进行测试(目前它已完全崩溃)。我很高兴你提醒我我的错误,你是复杂的
      CREATE MEMORY TABLE PUBLIC.PEDAGOGICALNEED(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) NOT NULL PRIMARY KEY,DESCRIPTION VARCHAR(255),NAME VARCHAR(255))
      ALTER TABLE PUBLIC.PEDAGOGICALNEED ALTER COLUMN ID RESTART WITH 1
      CREATE MEMORY TABLE PUBLIC.PEDAGOGICALNEED_PEDAGOGICALNEED(
          PEDAGOGICALNEED_ID BIGINT NOT NULL,
          PARENTS_ID BIGINT NOT NULL,
          CHILDREN_ID BIGINT NOT NULL,
          PRIMARY KEY(PEDAGOGICALNEED_ID,CHILDREN_ID),
          CONSTRAINT FK_GSX50JH17YMGUMDQ7ADD0Y0Y5 FOREIGN KEY(PARENTS_ID) REFERENCES PUBLIC.PEDAGOGICALNEED(ID),
          CONSTRAINT FK_L6QY3L7AMTRVX1O62WVS6C9X8 FOREIGN KEY(PEDAGOGICALNEED_ID) REFERENCES PUBLIC.PEDAGOGICALNEED(ID),
          CONSTRAINT FK_EHV0QET4GVHBX733YJV6Q9KQD FOREIGN KEY(CHILDREN_ID) REFERENCES PUBLIC.PEDAGOGICALNEED(ID))
      
      @Id
      @GeneratedValue(strategy=GenerationType.IDENTITY)
      private Long id;
      
      @Entity
      public class Node {
      
          @Id
          public int id;
      
          public String nodeName;
      
          @ManyToMany
          @JoinTable(name="relationships")
          public List<Node> parents;
      
          @ManyToMany(mappedBy="parents")
          public List<Node> children;
      
          public static void main(String[] args) {
              EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("persistenceUnit");
              EntityManager entityManager = entityManagerFactory.createEntityManager();
              EntityTransaction transaction = entityManager.getTransaction();
              transaction.begin();
              entityManager.persist(new Node());
              transaction.commit();
              entityManager.close();
          }
      
      }
      
      @ManyToMany(targetEntity = PedagogicalNeedEntity.class, fetch = FetchType.LAZY)
      @JoinTable(name="PedagogicalNeed_parents")
      private Set<PedagogicalNeed> parents = new HashSet<PedagogicalNeed>(0);
      
      @ManyToMany(targetEntity = PedagogicalNeedEntity.class, fetch = FetchType.LAZY)
      @JoinTable(name="PedagogicalNeed_children")
      private Set<PedagogicalNeed> children = new HashSet<PedagogicalNeed>(0);