Hibernate JPA 2.0多对多和附加列

Hibernate JPA 2.0多对多和附加列,hibernate,jakarta-ee,orm,jboss7.x,jpa-2.0,Hibernate,Jakarta Ee,Orm,Jboss7.x,Jpa 2.0,我试图在JPA2.0(JBoss 7.1.1)中建立一个多个关系,并在关系中增加一列(粗体,如下所示),如: Employer EmployerDeliveryAgent DeliveryAgent (id,...) (employer_id, deliveryAgent_id, **ref**) (id,...) 我不希望有重复的属性,因此我希望应用中介绍的第二个解决方案。但我无法让它工作,我会出现以下错误: 嵌入的ID类不应该包含关系映射(

我试图在JPA2.0(JBoss 7.1.1)中建立一个多个关系,并在关系中增加一列(粗体,如下所示),如:

Employer           EmployerDeliveryAgent             DeliveryAgent
(id,...)   (employer_id, deliveryAgent_id, **ref**)  (id,...)
我不希望有重复的属性,因此我希望应用中介绍的第二个解决方案。但我无法让它工作,我会出现以下错误:

  • 嵌入的ID类不应该包含关系映射(实际上规范中是这么说的)
  • 在属性“employerDeliveryAgent”中,“mapped by”值“pk.deliveryAgent”无法解析为目标实体上的属性
  • 在属性“employerDeliveryAgent”中,“mapped by”值“pk.employer”不能解析为目标实体上的属性
  • 无法解析覆盖属性“pk.deliveryAgent”的持久类型
  • 无法解析覆盖属性“pk.employer”的持久类型 那个链接上的许多人说它工作得很好,所以我想我的环境中有些不同,可能是JPA或Hibernate版本。所以我的问题是:如何使用JPA2.0(JBoss7.1.1/使用Hibernate作为JPA实现)实现这种场景?为了补充这个问题:我应该避免使用复合键,而是使用普通生成的id和唯一约束吗

    提前谢谢


    Obs.:我没有在这里复制我的源代码,因为它本质上是上面链接中的源代码的副本,只是具有不同的类和属性名称,所以我想这是没有必要的。

    好的,我根据在

    此解决方案不会在数据库上生成重复的属性,但会在我的JPA实体中生成重复的属性(这是非常可以接受的,因为您可以将额外的工作传递给构造函数或方法-它最终是透明的)。数据库中生成的主键和外键100%正确

    如链接所述,我不能使用@PrimaryKeyJoinColumn,而是使用@JoinColumn(name=“projectId”,updateable=false,insertable=false,referencedColumnName=“id”)。另一件值得一提的事情是:我必须使用EntityManager.persist(association),链接中的示例中缺少了它

    因此,我的最终解决方案是:

    @Entity
    public class Employee {
      @Id
      private long id;
      ...
      @OneToMany(mappedBy="employee")
      private List<ProjectAssociation> projects;
      ...
    }
    

    首先,您需要生成一个
    EmployerDeliveryAgentPK
    类,因为它有多个PK:

    @Embeddable
    public class EmployerDeliveryAgentPK implements Serializable {
    
        @Column(name = "EMPLOYER_ID")
        private Long employer_id;
    
        @Column(name = "DELIVERY_AGENT_ID")
        private Long deliveryAgent_id;
    }
    
    接下来,您需要创建一个
    EmployeerDeliveryAgent
    类。此类表示
    雇主
    送货代理
    之间的多对多关系:

    @Entity
    @Table(name = "EmployerDeliveryAgent")
    public class EmployerDeliveryAgent implements Serializable {
    
        @EmbeddedId
        private EmployerDeliveryAgentPK id;
    
        @ManyToOne
        @MapsId("employer_id") //This is the name of attr in EmployerDeliveryAgentPK class
        @JoinColumn(name = "EMPLOYER_ID")
        private Employer employer;
    
        @ManyToOne
        @MapsId("deliveryAgent_id")
        @JoinColumn(name = "DELIVERY_AGENT_ID")
        private DeliveryAgent deliveryAgent;    
    }
    
    之后,在
    Employer
    类中,您需要添加:

        @OneToMany(mappedBy = "deliveryAgent")
        private Set<EmployerDeliveryAgent> employerDeliveryAgent = new HashSet<EmployerDeliveryAgent>();
    
        @OneToMany(mappedBy = "employer")
        private Set<EmployerDeliveryAgent> employer = new HashSet<EmployerDeliveryAgent>();
    
    就这些!祝你好运

    答案来自和帮助,但在关联表中使用ID是多余的。类中既有关联的实体,也有它们的ID。这不是必需的。您可以使用关联实体字段上的
    @Id
    简单地映射关联类中的关联实体

    @Entity
    public class Employer {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int id;
    
        @OneToMany(mappedBy = "employer")
        private List<EmployerDeliveryAgent> deliveryAgentAssoc;
    
        // other properties and getters and setters
    }
    
    @Entity
    public class DeliveryAgent {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int id;
    
        @OneToMany(mappedBy = "deliveryAgent")
        private List<EmployerDeliveryAgent> employerAssoc;
    
        // other properties and getters and setters
    }
    
    仍然需要关联PK类。请注意,字段名称应与关联类中的字段名称完全对应,但类型应为关联类型中id的类型

    public class EmployerDeliveryAgentId implements Serializable {
    
        private int employer;
        private int deliveryAgent;
    
        // getters/setters and most importantly equals() and hashCode()
    }
    

    非常感谢,我花了两天时间试图解决这个问题。我认为在
    DeliveryAgent
    类中,我们应该映射
    EmployeerDelivery
    类,而不是
    Employeer
    类。因此,
    DeliveryAgent
    类中的代码应该类似于
    private-Set-employerDeliveryAgent=new-HashSet(),与
    雇主
    类中的代码相同。是否需要重写
    equals()
    hashcode()
    ?(假设我不打算将持久类的实例放在一个集合中,也不打算使用分离实例的重新附加)这是你能得到的最干净的解决方案,做得好。任何人都可以提供插入或删除示例。非常酷,谢谢。问题。。。如果我还将生成的@id列放入association类中(在您的示例中为EmployerDeliveryAgent),则会得到一个NPE。但是我想要一个RDBMS长PK。。。你说呢?有办法吗?拧上我的代理键?如何通过一个额外的字段id绑定实体,而不是
    布尔isProjectLead
    ?为什么需要id类?优雅的解决方案:
        @OneToMany(mappedBy = "employer")
        private Set<EmployerDeliveryAgent> employer = new HashSet<EmployerDeliveryAgent>();
    
    @Entity
    public class Employer {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int id;
    
        @OneToMany(mappedBy = "employer")
        private List<EmployerDeliveryAgent> deliveryAgentAssoc;
    
        // other properties and getters and setters
    }
    
    @Entity
    public class DeliveryAgent {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int id;
    
        @OneToMany(mappedBy = "deliveryAgent")
        private List<EmployerDeliveryAgent> employerAssoc;
    
        // other properties and getters and setters
    }
    
    @Entity
    @Table(name = "employer_delivery_agent")
    @IdClass(EmployerDeliveryAgentId.class)
    public class EmployerDeliveryAgent {
    
        @Id
        @ManyToOne
        @JoinColumn(name = "employer_id", referencedColumnName = "id")
        private Employer employer;
    
        @Id
        @ManyToOne
        @JoinColumn(name = "delivery_agent_id", referencedColumnName = "id")
        private DeliveryAgent deliveryAgent;
    
        @Column(name = "is_project_lead")
        private boolean isProjectLead;
    }
    
    public class EmployerDeliveryAgentId implements Serializable {
    
        private int employer;
        private int deliveryAgent;
    
        // getters/setters and most importantly equals() and hashCode()
    }