有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java无法在JPA2中将继承的复合键用作派生id

我是否做错了什么,或者这在JPA2/eclipselink中不受支持,让我用代码解释一下

 @Embeddable
public class MemberID implements Serializable {
    private String e_mail;
    private String password;
        //...no-arg constructor, getter and setter

下面的实体使用MemberID作为复合键

@Entity
@Table(name="MEMBER_DETAILS")
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="GROUPNAME", discriminatorType=DiscriminatorType.STRING,   length=20)
public class Member_Details implements Serializable {

@EmbeddedId
private MemberID memberIdentity;
...other code

下面的实体扩展了成员的详细信息,因此继承了其密钥

@Entity
@Table(name="INDIVIDUAL_USER")
@DiscriminatorValue("INDIVIDUAL_USER")
public class Individual_User extends Member_Details implements Serializable {    
    @OneToMany(mappedBy="userinfo", fetch=FetchType.EAGER)
private List<UserComment> userComments = new ArrayList<UserComment>();
... other code

下面是一个复合键,其中包含MemberID

@Embeddable
public class CommentID implements Serializable { 
private MemberID memberId;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="TIME_POSTED")
private Date timeOfComment;
...other code

下面的实体使用CommentID作为其复合键。我希望它依赖于实体个人用户,因此使用派生id。这就是为什么MemberID是其复合密钥的一部分

@Entity
@Table(name="USER_COMMENTS")
public class UserComment implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private CommentID commentIdentity;

@MapsId("memberId")
@ManyToOne
@JoinColumns({
@JoinColumn(name="E_MAIL", referencedColumnName="E_MAIL"),
@JoinColumn(name="PASSWORD", referencedColumnName="PASSWORD")
})
private Individual_User userinfo;
...other code

当我尝试部署时,出现了以下异常:

Caused by: Exception [EclipseLink-7321] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The field [MEMBER_DETAILS.PASSWORD] from the derived id mapping  [userinfo] from class [kariro.semaplace.talk.entities.UserComment] is an invalid id field from the reference class [kariro.semaplace.registration.entity.Individual_User]. Ensure there is a corresponding id mapping to that field. 

但是,当我将@ManyToOne关系从UserComment改为reffer,改为键入Member_Details,而不是其子类型Individual_User时,它不会出现任何问题,但我担心这会在以后带来更多问题,或损害应用程序的功能。 我真的不知道eclipselink是不允许继承ID被用作派生ID,还是我做错了什么。谁来帮帮我


共 (1) 个答案

  1. # 1 楼答案

    我不确定为什么会出现这种错误,但可以通过简化实体来完全避免这个问题

    1. 我首先想到的是,你用户的PK包括password。密码通常是可变的,而主键则不是。此外,你会期望有两个不同的用户使用相同的电子邮件但密码不同吗?可能不会。删除MemberID并将Member_Details更改为一个简单的@Ide_mail

      @Entity
      @Table(name="MEMBER_DETAILS")
      @Inheritance(strategy=InheritanceType.JOINED)
      @DiscriminatorColumn(name="GROUPNAME", discriminatorType=DiscriminatorType.STRING, length=20)
      public class Member_Details implements Serializable
      {
        @Id
        private String e_mail;
        private String password;
        // ...
      }
      

      CommentID也会改变:

      @Embeddable
      public class CommentID implements Serializable
      {
        private String e_mail;
      
        @Temporal(TemporalType.TIMESTAMP)
        @Column(name="TIME_POSTED")
        private Date timeOfComment;
      }
      

      而且UserComment上的@MapsId将更改为@MapsId("e_mail")

    2. 上面的更改应该足以避免您的问题,但如果是我,我也会去掉UserComment上的复合主键。简单来说,你可以给它一个UUID,然后在e_mailtimeOfComment上加一个唯一的约束