【发布时间】:2014-03-25 16:44:38
【问题描述】:
我在使用 Hibernate 和 Spring MVC 插入具有 @OneToMany 关系的记录时遇到问题。我可以成功插入记录,而无需向 @OneToMany 集合添加任何内容。但是,在添加集合记录时,它无法说明存在 SQLIntegrityConstraintViolationException。
我当前的映射(注解风格)代码如下:
Contact.java
package mil.navy.navsupbsc.entity;
import java.util.Collection;
import java.util.LinkedHashSet;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
@Entity
@Table(name = "CONTACT2")
public class Contact extends Auditable {
public Contact() {
}
// Create with mandatory fields
public Contact(long id, Salutation salutation, String firstName,
String middleInitial, String lastName,
MilitaryCivilianInformation milCivInfo) {
this.setContactId(id);
this.setSalutation(salutation);
this.setFirstName(firstName);
this.setMiddleInitial(middleInitial);
this.setLastName(lastName);
this.setMilitaryCivilianInformation(milCivInfo);
}
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
@SequenceGenerator(name = "CONTACT_SEQ")
@Column(name = "CONTACT_ID")
private Long contactId;
@Fetch(FetchMode.SUBSELECT)
@OneToMany(cascade = { CascadeType.ALL, CascadeType.REMOVE }, mappedBy = "contact", orphanRemoval = true)
private Collection<Email> emails = new LinkedHashSet<Email>();
/**
* @return the emails
*/
public Collection<Email> getEmails() {
for (Email email : emails) {
email.getEmailType();
}
return emails;
}
/**
* @param emails
* the emails to set
*/
public void setEmails(Collection<Email> emails) {
this.emails.clear();
for (Email email : emails) {
this.addEmail(email);
}
}
public void addEmail(Email email) {
email.setContact(this);
this.getEmails().add(email);
}
[...more Getters / Setters and fields]
}
电子邮件.java
package mil.navy.navsupbsc.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.codehaus.jackson.annotate.JsonBackReference;
/**
* Implements Auditing Properties
*/
@Entity
@Table(name = "EMAIL")
public class Email extends Auditable {
private static final long serialVersionUID = -4833322552325183301L;
@Id
@GeneratedValue
@SequenceGenerator(name = "EMAIL_SEQ")
@Column(name = "EMAIL_ID")
private long emailId;
@JsonBackReference
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CONTACT_FK")
private Contact contact;
[More fields]
public Contact getContact() {
return contact;
}
public void setContact(Contact contact) {
this.contact = contact;
}
public long getEmailId() {
return emailId;
}
public void setEmailId(long emailId) {
this.emailId = emailId;
}
[more getters / setters]
}
ContactDAOImpl(我已经尝试了很多变体,但都没有成功)
public void saveContact(Contact contact) {
Session session = sessionFactory.getCurrentSession();
Collection<Email> emailCollection = new LinkedHashSet<Email>();
emailCollection = contact.getEmails();
Contact contactToSave;
long contactId;
if (contact.getContactId() == 0 || contact.getContactId() == null) {
contactToSave = new Contact((long) 0, contact.getSalutation(),
contact.getFirstName(), contact.getMiddleInitial(),
contact.getLastName(),
contact.getMilitaryCivilianInformation());
session.save(contactToSave);
session.flush();
for (Email email : emailCollection) {
// email.setContact(contactToSave);
contactToSave.addEmail(email);
}
session.saveOrUpdate(contactToSave);
session.flush();
session.clear();
}
对此的任何帮助都非常感谢。我有一个以前的版本可以正确更新记录,但似乎无法解决保存新记录。我最初也使用了从 Web 服务传入的联系人,但我试图在 DAO 中创建一个新记录,以消除我的代码的最新变体中的潜在问题。
另外,我知道有很多类似的问题,但我尝试了很多答案都没有成功(因此提出了新问题)。
感谢您的帮助!
更新
我检查了数据层在初始保存后返回的 ID,并验证(不成功)相同的 ID 已保存在数据库中。返回的 ID 与保存的 ID 不同。例如,最新的保存显示联系人 ID 为“1129”,初始保存后返回的联系人。我从数据库中检索了联系人 ID '1129' - 它成功返回了联系人。关闭事务后,直接查看数据库中的数据。数据库将“193”显示为联系人 ID,而不是“1129”。有什么想法吗??
【问题讨论】:
-
你也可以发布堆栈跟踪吗?
-
@Nivas - 我发现了问题......原来这是因为直接在数据库中使用触发器,而不是在插入之前使用通过 Hibernate 生成的值。我也有不正确的语法来指示 Hibernate 使用我的自定义序列生成器而不是默认的 Hibernate 序列生成器。由于它现在可以工作,我没有堆栈跟踪。感谢您查看问题!如果您对我发布的解决方案有任何进一步的建议,请随时发布 - 我还是 Hibernate 和 JAVA 的新手 - 所以我非常感谢我收到的帮助!
标签: java spring hibernate spring-mvc