【问题标题】:~"IdClass not defined" in JpaRepository, for an inherited @OneToOne @Id~ JpaRepository 中的“IdClass not defined”,用于继承的@OneToOne @Id
【发布时间】:2017-08-10 01:57:59
【问题描述】:

我正在尝试创建一个 jpa 存储库,但外键主键存在问题。尽管在抽象基类 (MessageDestination) 中指定了它,但它似乎在专用 MessageDestination 类的存储库中是不可见的(例如 MessageDestinationRoom)。

[...] 嵌套异常是 org.springframework.beans.factory.BeanCreationException:创建名为“messageDestinationRoomDAO”的 bean 时出错:调用 init 方法失败;嵌套异常是 java.lang.IllegalArgumentException:此类 [class com.chat.message.entity.MessageDestinationRoom] 未定义 IdClass

@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Message implements Serializable {    
    @Id @GeneratedValue(strategy = GenerationType.TABLE)
    private Long id;

    @OneToOne(targetEntity = MessageDestination.class,
              cascade=CascadeType.ALL, mappedBy="msg")
    @NotNull
    private MessageDestination dest;

    //...
}

@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class MessageDestination implements Serializable {      
    @Id @OneToOne(cascade=CascadeType.ALL)
    private Message msg;
}

@Entity
public class MessageDestinationRoom extends MessageDestination {        
    @OneToOne @NotNull
    private Room destRoom;

    //...
}

public interface MessageDestinationRoomDAO
extends JpaRepository<MessageDestinationRoom, Message> {
    public Set<MessageDestinationRoom> findMessageDestinationRoomByDestRoom
        (Room dest);
}

为了解决这个问题,我看到我可以将MessageDestination 注释为@MappedSuperclass,但这不起作用,因为它需要是@Entity 才能存储在Message 中。可悲的是,这是不可能的:

org.hibernate.AnnotationException: 不能同时使用@Entity 和@MappedSuperclass 注释实体

有什么想法吗?谢谢...

【问题讨论】:

    标签: java spring hibernate jpa spring-data-jpa


    【解决方案1】:

    当我使用基于 @oneToMany 和 @ManyToOne 注释的映射时,我也遇到了同样的问题。

    基本上我所做的错误是在抛出错误“未定义 IdClass”的类中具有复合键,即更多一个 @Id 注释用于两个成员变量,因此它被视为复合Key 并且由于 hibernate 期望在复合键的情况下需要定义一个单独的 Key 类,因此失败即将到来。

    【讨论】:

      【解决方案2】:

      等待更好的答案,因为我发现的唯一解决方案非常难看。这包括拆分主键和外键,因此存在冗余......

      这个:

      @Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
      public abstract class MessageDestination implements Serializable {      
          @Id @OneToOne(cascade=CascadeType.ALL)
          private Message msg;
      }
      
      public interface MessageDestinationRoomDAO
      extends JpaRepository<MessageDestinationRoom, Message> {
          public Set<MessageDestinationRoom> findMessageDestinationRoomByDestRoom
              (Room dest);
      }
      

      变成这样:

      @Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
      abstract class MessageDestination implements Serializable {      
          @Id @GeneratedValue(strategy = GenerationType.TABLE)
          private Long id;
      
          @OneToOne(cascade=CascadeType.ALL)
          private Message msg;
      }
      
      interface MessageDestinationRoomDAO
      extends JpaRepository<MessageDestinationRoom, Long> {
          public Set<MessageDestinationRoom> findMessageDestinationRoomByDestRoom
              (Room dest);
      }
      

      【讨论】:

        【解决方案3】:

        由于您使用的是按类继承策略,并且您没有任何映射的超类(因此每个实体都必须有自己的 id)。

        您可以将您的 MessageDestination 实体注释为 @MappedSuperClass 并从 MessageDestination 中删除 @Entity。默认情况下,它的每个子类都将继承其所有字段,包括 @Id 字段

        【讨论】:

        • 已经试过了。实际上我使用TABLE_PER_CLASS 而不是SINGLE_TABLE 策略。您的建议会触发以下异常:org.hibernate.AnnotationException: Unknown mappedBy in: com.test.Message.dest, referenced property unknown: com.test.MessageDestination.msg。谢谢你的时间。 :)
        猜你喜欢
        • 1970-01-01
        • 2012-12-02
        • 2019-09-19
        • 2014-03-25
        • 2015-08-20
        • 1970-01-01
        • 1970-01-01
        • 2015-03-16
        • 2020-12-03
        相关资源
        最近更新 更多