Java @OneToMany SQLIntegrityConstraintViolationException插入时出错(休眠)
我在使用Hibernate和Spring MVC插入@OneToMany关系的记录时遇到问题。我可以在不向@OneToMany集合添加任何内容的情况下成功插入记录。但是,在添加集合记录时,它无法声明存在SQLIntegrityConstraintViolationException 我当前的映射代码(注释样式)如下所示: Contact.javaJava @OneToMany SQLIntegrityConstraintViolationException插入时出错(休眠),java,spring,hibernate,spring-mvc,Java,Spring,Hibernate,Spring Mvc,我在使用Hibernate和Spring MVC插入@OneToMany关系的记录时遇到问题。我可以在不向@OneToMany集合添加任何内容的情况下成功插入记录。但是,在添加集合记录时,它无法声明存在SQLIntegrityConstraintViolationException 我当前的映射代码(注释样式)如下所示: Contact.java package mil.navy.navsupbsc.entity; import java.util.Collection; import jav
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]
}
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(联系人联系人){
Session Session=sessionFactory.getCurrentSession();
Collection emailCollection=新建LinkedHashSet();
emailCollection=contact.getEmails();
接触式保存;
长联系人ID;
if(contact.getContactId()==0 | | contact.getContactId()==null){
contactToSave=新联系人((长)0,Contact.getSalitation(),
contact.getFirstName(),contact.getMiddleInitial(),
contact.getLastName(),
contact.getMilitaryCivilianInformation());
session.save(contactToSave);
session.flush();
用于(电子邮件:emailCollection){
//email.setContact(contactToSave);
contactToSave.addEmail(电子邮件);
}
会话。保存或更新(contactToSave);
session.flush();
session.clear();
}
非常感谢您对此提供的任何帮助。我有一个正确更新记录的早期版本,但似乎无法保存新记录。我最初也使用了从web服务传入的联系人,但我尝试在DAO中创建一个新记录,以消除最新版本代码中的潜在问题
此外,我知道有许多类似的问题,但我尝试了许多答案,但都没有成功(因此出现了新问题)
谢谢你的帮助
更新
我检查了数据层在初始保存和验证后返回的ID(未成功)数据库中保存了相同的ID。返回的ID与保存的ID不同。例如,最新保存显示联系人ID为“1129”,初始保存后返回的联系人ID为“1129”。我从数据库中检索了联系人ID为“1129”的联系人,它成功返回了联系人。关闭事务后,我查看了数据直接存储在数据库中。数据库显示联系人ID为“193”,而不是“1129”。有什么想法吗???我发现了我遇到的问题 在创建Hibernate实体定义之前,我直接在数据库中创建了序列和触发器。我还在JAVA Hibernate代码中的实体定义中指定了相同的序列。但是,我生成序列的语法不完整 由于生成序列的语法不完整,JAVA代码使用默认的HIBERNATE_序列生成器,而不是我创建的序列。HIBERNATE从HIBERNATE_序列返回序列值(在插入数据库之前创建ID)。但是,在将值插入数据库之前,Oracle立即运行我的自定义序列,并将联系人ID分配给新生成的值 因此,当我试图向集合添加值时,Insert语句试图使用Hibernate生成的序列值作为外键,而不是数据库生成的序列值 为了确保Hibernate代码和数据库同步,我从数据库中删除了ContactID触发器。基于StackOverflow()中的另一个问题,我将Contact.JAVA ContactID声明的JAVA Hibernate代码更新为:
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CONTACT_SEQ")
@SequenceGenerator(name = "CONTACT_SEQ", sequenceName = "contact_seq", allocationSize = 1)
@Column(name = "CONTACT_ID")
private Long contactId;
谢天谢地,这解决了这个问题。JAVA Hibernate代码现在通过我指定的序列创建ID。然后数据库成功地将这些值插入到数据库中
我还可以将我的保存简化为:
public void saveContact(Contact contact) {
Session session = sessionFactory.getCurrentSession();
if (contact.getContactId() == 0 || contact.getContactId() == null) {
session.save(contact);
session.flush();
}
}
我确信我需要再次更改它,以说明更新联系人的原因-可能使用saveOrUpdate()而不是save().您也可以发布stacktrace吗?@Nivas-我发现了问题所在…原来是因为直接在数据库中使用触发器,而不是在插入之前使用通过Hibernate生成的值。我还使用了错误的语法来指示Hibernate使用自定义序列生成器,而不是默认的Hibernate序列生成器nce生成器。由于它现在可以工作,我没有堆栈跟踪。不过感谢您关注这个问题!如果您对我发布的解决方案有任何进一步的建议,请随时发布它们-我对Hibernate和JAVA仍然是新手-因此我非常感谢收到的帮助!
public void saveContact(Contact contact) {
Session session = sessionFactory.getCurrentSession();
if (contact.getContactId() == 0 || contact.getContactId() == null) {
session.save(contact);
session.flush();
}
}