Java @OneToMany SQLIntegrityConstraintViolationException插入时出错(休眠)

Java @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

我在使用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]

}
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();

    }

}