簡體   English   中英

使用具有3層結構的@IdClass在主鍵中使用復合鍵進行JPA 2 Hibernate映射

[英]JPA 2 Hibernate mapping with composite key in primary key using @IdClass with 3 tier structure

這個問題非常類似於: JPA(Hibernate,EclipseLink)映射:為什么這段代碼不起作用(使用JPA 2.0,@ EmbeddedId復合PK-FK的2個關系鏈)?

實際上我的唯一(從我發現的有意義的)差異是我使用@IdClass並且我很可能無法切換到與hibernate不同的提供者。

但無論如何這里是代碼(刪除不重要的部分):

PermissionContextType.java

@Entity
@IdClass(PermissionContextTypePk.class)
public class PermissionContextType{
   @Id    
   private String id;    

   @Id
   @JoinColumn (name = "PROJECT", referencedColumnName = "ID")
   @ManyToOne ()
   private Project project;

   public static class PermissionContextTypePk implements Serializable{
       public String project;
       public String id;
       // ... eq and hashCode here ...
   }

}

PermissionContext.java

@Entity
@IdClass(PermissionContextPk.class)
public class PermissionContext{
   @Id
   private String id;

   @Id
   @JoinColumns ({
            @JoinColumn (name = "PROJECT", referencedColumnName = "PROJECT"),
            @JoinColumn (name = "PERMISSIONCONTEXTTYPE", referencedColumnName = "ID")
        })
   @ManyToOne
   private PermissionContextType permissionContextType;

   public static class PermissionContextPk implements Serializable{
      public String id;
      public PermissionContextTypePk permissionContextType;
      // ... eq and hashCode here ...
   }
}

Permission.java

@Entity
@IdClass(PermissionPk.class)
public class Permission{

   @Id
   private String id;

   @Id
   @JoinColumns ({
            @JoinColumn (name = "PROJECT", referencedColumnName = "PROJECT"),
            @JoinColumn (name = "PERMISSIONCONTEXTTYPE", referencedColumnName = "PERMISSIONCONTEXTTYPE"),
            @JoinColumn (name = "PERMISSIONCONTEXT", referencedColumnName = "ID")
        })
   @ManyToOne
   private PermissionContext permissionContext;

   public static class PermissionPk implements Serializable{
      public String id;        
      public PermissionContextPk permissionContext;
      // ... eq and hashCode here ...
   }
}

而我得到的是:

 org.hibernate.AssertionFailure: Unexpected nested component on the referenced entity when mapping a @MapsId: PermissionContext 
    Caused by: org.hibernate.AssertionFailure: org.hibernate.AssertionFailure: Unexpected nested component on the referenced entity when mapping a @MapsId: PermissionContext

有沒有人知道這是一個hibernate錯誤,我應該將它發布在他們的問題跟蹤系統上(並祈禱我能夠更新到給定的hibernate版本)或者我的綁定實體的方式是否存在根本錯誤?

我已經使用EAP 6.1(4.2.0)上的hibernate實現以及wildfly(不知道哪一個)進行了檢查。

好的,所以這是我到目前為止所發現的:

謝謝我的朋友: https//hibernate.atlassian.net/browse/HHH-5764這很可能就是這種行為的原因。

我發現了一個解決方法:

Permission.java:

@Entity
@IdClass(PermissionPk.class)
public class Permission{

   @Id
   private String id;

// for the next 3 fields there are no public acessors, so the public API of the class was not changed !
   @Id
   @Column(name = "PROJECT")
   private String projectId;

   @Id
   @Column(name = "PERMISSIONCONTEXTTYPE")
   private String permissionContextTypeId;

   @Id
   @Column(name = "PERMISSIONCONTEXT")
   private String permissionContextId;


   @JoinColumns ({
            @JoinColumn (name = "PROJECT", referencedColumnName = "PROJECT", updatable = false, insertable = false),
            @JoinColumn (name = "PERMISSIONCONTEXTTYPE", referencedColumnName = "PERMISSIONCONTEXTTYPE", updatable = false, insertable = false),
            @JoinColumn (name = "PERMISSIONCONTEXT", referencedColumnName = "ID", updatable = false, insertable = false)
        })
   @ManyToOne
   private PermissionContext permissionContext;

   public static class PermissionPk implements Serializable{      
// previously they where private as well, but removed public constructor for the sake of simplicity of the question - so no changes where necesary in public API of the class !
      private String id;        
      private String projectId;        
      private String permissionContextTypeId;
      private String permissionContextId;

   public PermissionPk () {}

    public PermissionPk (String aId, PermissionContextPk aPermissionContext) {
        this.id = aId;
        permissionContextId = aPermissionContext.id;
        permissionContextTypeId = aPermissionContext.permissionContextType.id;
        projectId = aPermissionContext.permissionContextType.project;
    }  
... eq and hashCode here ...
   }
}

這個解決方法的好處是它不會以任何方式更改類的公共API(唯一的變化是我需要在Pk的上下文中創建字段,並且上下文類型對PermissionPk可見 - 它們之前是私有的,只有一個公共構造函數[但同樣簡化了問題]),也沒有改變jpql查詢,同時解決方法是可擴展的(任何層數 - 只要每個偶數pk不包含另一個pk),所以如果將解決錯誤,將很容易刪除變通方法。

我仍然樂意接受對我的解決方法或問題本身的任何評論。

今天我找到了另一種解決方法:)你可以完全省略@IdClass並使用hibernate特定的能力來動態創建復合鍵,因為它顯然不受此bug的影響。 這里的缺點是:

  1. 它完全是Hibernate特有的,不是JPA所涵蓋的。
  2. 你不能做em.find(ClassName.class,new ClassPk(args ...)),因為根本沒有ClassPk。

但是,如果你可以使用除休眠之外的任何東西,你也可以使用沒有這個bug的東西 - 所以可能1真的不是問題。 並且你可能不需要為這個實體提供em.find(或者可以通過session或jpql查詢來創建它)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM