2017-04-17 47 views
0

我有這些實體要與雙向關聯。JPA:「無法寫入表中的重複鍵」以獲得一對一關係

憑據:

@Entity 
@Access(AccessType.PROPERTY) 
@Table(name = "credential") 
public class Credential extends MetaInfo implements Serializable { 



    ... 
    private Email email; 

    ... 

    @OneToOne(cascade = CascadeType.ALL, optional = false, orphanRemoval = true) 
    @JoinColumn(name="email", referencedColumnName="email_address") 
    public Email getEmail() { 
     return email; 
    } 

    public void setEmail(Email email) { 
     this.email = email; 
    } 

    ... 
} 

電子郵件:

@Entity 
@Access(AccessType.PROPERTY) 
@Table(name = "email") 
public class Email extends MetaInfo implements Serializable{ 

    ... 
    private Credential credential; 

    public Email() { 
    } 

    public Email(String emailAddress) { 
     this.emailAddress = emailAddress; 
    }  

    @Id 
    @Column(name="email_address") 
    public String getEmailAddress() { 
     return emailAddress; 
    } 

    public void setEmailAddress(String emailAddress) { 
     this.emailAddress = emailAddress; 
    } 

    @OneToOne(mappedBy = "email", optional=false) 
    public Credential getCredential() { 
     return credential; 
    } 

    public void setCredential(Credential credential) { 
     this.credential = credential; 
    } 
} 

CredentialRepository類我測試是否傳入的電子郵件 沒有分配到任何用戶除了與通過用戶名的用戶-in作爲第二個(可選)參數:

@Override 
public boolean emailIsAssigned(String... args) { 
    assert(args.length > 0); 
    if(InputValidators.isValidEmail.test(args[0])){ 
     EntityManager em = entityManagerFactory.createEntityManager(); 
     try { 
      TypedQuery<Long> count = em.createQuery("SELECT COUNT(e) " 
        + "FROM Email e WHERE e.emailAddress " 
        + "= :email AND e " 
        + "IN (SELECT c.email FROM Credential c WHERE c.username " 
        + "!= :username)", Long.TYPE).setParameter("email", args[0]) 
        .setParameter("username", null); 
      if(InputValidators.stringNotNullNorEmpty.apply(args[1])){ 
      //only if the username has been provided 
       count.setParameter("username", args[1]); 
      } 
      return count.getSingleResult() > 0; 
     } catch (Exception e) { 
      System.out.println(e.getMessage()); 
      return false; 
     } finally { 
      em.close(); 
     } 
    }else{ 
     throw new NotAValidEmailException(args[0] + " is not a" 
       + " valid email address."); 
    } 
} 

因此,上面的args[0]是被測試的電子郵件,args[1]是被測試的用戶名。

這是導致我的問題(注意,之前我已經試驗成功插入,更新,甚至emailIsAssigned方法,但測試沒有這似乎使問題c.email部分:

@Test 
public void emailAlreadyExistsTest(){ 
    assertTrue(credentialRepo.emailIsAssigned("[email protected]")); 
} 

而且這是錯誤信息,我有:

[EL Warning]: 2017-04-17 17:55:33.606--ServerSession(234430897)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException 
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Can't write; duplicate key in table '#sql-3e4_9a' 
Error Code: 1022 
Call: ALTER TABLE credential ADD CONSTRAINT FK_credential_email FOREIGN KEY (email) REFERENCES email (email_address) 
Query: DataModifyQuery(sql="ALTER TABLE credential ADD CONSTRAINT FK_credential_email FOREIGN KEY (email) REFERENCES email (email_address)") 

我將不勝感激,如果有人能夠給我一個忠告,我總是可以只改變電子郵件爲String和其標記爲「獨一無二」。,但我覺得沒有理由選擇的方法不工作。

我使用MySQL作爲數據庫供應商和Eclipse-Link JPA實現。我確實試圖「硬化」FK約束的名稱,但無濟於事。數據庫和所有表具有相同的排序規則(utf8_unicode_ci)。

回答

0

嘗試刪除類電子郵件的主鍵,因爲「extends MetaInfo」

+0

恐怕這是不可能的。刪除'@ Id'註釋會使.java文件不可編譯。除了MetaInfo只是一個抽象類('@ MappedSuperclass') - 它本身沒有主鍵。 – vasigorc