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 楼答案
尝试删除类电子邮件的主键,因为“扩展元信息”