有 Java 编程相关的问题?

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

java JPA:OnetoOne关系的“无法写入;表中重复键”

我有这些我想双向关联的实体

凭证:

@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类中,我正在测试邮件是否通过 未分配给任何用户,但用户名作为第二个(可选)参数传入的用户除外:

@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("existing_email@yahoo.ca"));
}

这是我收到的错误信息:

  [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)")

如果有人能给我一点建议,我将不胜感激。我总是可以将电子邮件更改为字符串,并在@Column中将其标记为“唯一”,但我觉得所选择的方法没有理由不起作用

我使用MySQL作为DB供应商,并使用Eclipse Link JPA实现。我确实试图“硬更改”FK约束的名称,但没有效果。DB和所有表都有相同的排序规则(utf8_unicode_ci)


共 (1) 个答案

  1. # 1 楼答案

    尝试删除类电子邮件的主键,因为“扩展元信息”