java - Hibernate实体生成奇怪的sql并尝试保存重复的条目

标签 java sql hibernate

我有以下实体

@Entity
@Table(name="mail_event")
@Cacheable(false)
public class MailEvent extends DomainObject {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    private Long id;    

    @JoinTable(name="mail_event_recipients")
    @ManyToMany(fetch=FetchType.EAGER)
    private Set<User> recipients = new HashSet<User>();

    @Column(length=255)
    @Basic(optional=false)
    private String subject;

    @Column(length=255)
    @Basic(optional=false)
    private String fromName;

    @Column(length=255)
    @Basic(optional=false)
    private String fromEmail;

    @Lob
    @Basic(optional=false)
    private String messageBody;

    /*
     * Any users that should appear in the reply-to part of the email header are added here
     */
    @JoinTable(name="mail_event_reply_to")
    @ManyToMany(fetch=FetchType.EAGER)
    private Set<User> replyTo = new HashSet<User>();

    public MailEvent(){}

    public MailEvent(
                    final String subject,
                    final String messageBody,
                    final User recipient,
                    final String fromName,
                    final String fromEmail){
        this(subject,messageBody,recipient,fromName,fromEmail,null);
    }

    public MailEvent(
                    final String subject,
                    final String messageBody,
                    final Collection<User> recipients,
                    final String fromName,
                    final String fromEmail){
        this(subject,messageBody,recipients,fromName,fromEmail,null);
    }

    public MailEvent(
                    final String subject,
                    final String messageBody,
                    final User recipient,
                    final String fromName,
                    final String fromEmail,
                    final Collection<User> replyTo){
        this.subject = subject;
        this.messageBody = messageBody;
        this.recipients.add(recipient);
        this.fromName = fromName;
        this.fromEmail = fromEmail;
        if( replyTo != null )
            this.replyTo.addAll(replyTo);   
    }

    public MailEvent(           
                    final String subject,
                    final String messageBody,
                    final Collection<User> recipients,
                    final String fromName,
                    final String fromEmail,
                    final Collection<User> replyTo
                    ){
        this.subject = subject;
        this.messageBody = messageBody;
        this.recipients.addAll(recipients);
        this.fromName = fromName;
        this.fromEmail = fromEmail;
        if( replyTo != null )
            this.replyTo.addAll(replyTo);       

    }

    public Long getId() {
        return id;
    }

    public Set<User> getRecipients() {
        return recipients;
    }

    public void setRecipients(Set<User> recipients) {
        this.recipients = recipients;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public String getSubject() {
        return subject;
    }

    public String getFromName() {
        return fromName;
    }

    public void setFromName(String fromName) {
        this.fromName = fromName;
    }

    public String getFromEmail() {
        return fromEmail;
    }

    public void setFromEmail(String fromEmail) {
        this.fromEmail = fromEmail;
    }

    public String getMessageBody() {
        return messageBody;
    }

    public void setMessageBody(String messageBody) {
        this.messageBody = messageBody;
    }

    public Set<User> getReplyTo() {
        return replyTo;
    }

    public void setReplyTo(Set<User> replyTo) {
        this.replyTo = replyTo;
    }

    @Override
    public int hashCode() {
        final int weight = 31;
        int result = 17;

        result = weight * result + ((id == null) ? 0 : (int) (id ^ (id >>> 32)));

        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (this.getClass() != obj.getClass())
            return false;

        MailEvent other = (MailEvent) obj;

        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;

        return true;
    }



}

Hibernate 从中生成下表:

为什么我得到的索引是相等的?另外,当我尝试保存此类的对象时,出现以下异常:

2012 Jan 12 13:18:42,980[ERROR] - RequestCycle - Could not execute JDBC batch update; SQL [insert into mail_event_recipients (mail_event_id, recipients_id) values (?, ?)]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
org.springframework.dao.DataIntegrityViolationException: Could not execute JDBC batch update; SQL [insert into mail_event_recipients (mail_event_id, recipients_id) values (?, ?)]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
    at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:637)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:102)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:471)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    at $Proxy84.save(Unknown Source)
    at se.su.dsv.scipro.data.controllers.impl.NotificationControllerImpl.processNotification(NotificationControllerImpl.java:111)
    at se.su.dsv.scipro.data.controllers.impl.NotificationControllerImpl.notifyConferencePost(NotificationControllerImpl.java:181)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.wicket.proxy.LazyInitProxyFactory$JdkHandler.invoke(LazyInitProxyFactory.java:414)
    at org.apache.wicket.proxy.$Proxy1.notifyConferencePost(Unknown Source)
    at se.su.dsv.scipro.conference.panels.ConferencePanel$SendWallMessageForm$1.onSubmit(ConferencePanel.java:324)
    at org.apache.wicket.ajax.markup.html.form.AjaxButton$1.onSubmit(AjaxButton.java:101)
    at org.apache.wicket.ajax.form.AjaxFormSubmitBehavior.onEvent(AjaxFormSubmitBehavior.java:143)
    at org.apache.wicket.ajax.AjaxEventBehavior.respond(AjaxEventBehavior.java:177)
    at org.apache.wicket.ajax.AbstractDefaultAjaxBehavior.onRequest(AbstractDefaultAjaxBehavior.java:302)
    at org.apache.wicket.request.target.component.listener.BehaviorRequestTarget.processEvents(BehaviorRequestTarget.java:157)
    at org.apache.wicket.request.AbstractRequestCycleProcessor.processEvents(AbstractRequestCycleProcessor.java:92)
    at org.apache.wicket.RequestCycle.processEventsAndRespond(RequestCycle.java:1250)
    at org.apache.wicket.RequestCycle.step(RequestCycle.java:1329)
    at org.apache.wicket.RequestCycle.steps(RequestCycle.java:1436)
    at org.apache.wicket.RequestCycle.request(RequestCycle.java:545)
    at org.apache.wicket.protocol.http.WicketFilter.doGet(WicketFilter.java:486)
    at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:319)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:113)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:662)
Caused by: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:183)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206)
    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:375)
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
    at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:76)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:467)
    ... 44 more
Caused by: java.sql.BatchUpdateException: Duplicate entry '11642' for key 'PRIMARY'
    at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2020)
    at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1451)
    at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeBatch(NewProxyPreparedStatement.java:1723)
    at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
    ... 53 more

这让我相信 Hibernate 会尝试使用已用于新对象的 id。我该如何解决这个问题?

编辑:问题似乎是由于某种原因,我不允许在 mail_event_recipients 中多次输入相同的recipients_id。为什么会存在这种限制以及如何摆脱它?

最佳答案

您不能添加重复的条目,因为它是一个集合

The persistent collections injected by Hibernate behave like HashMap, HashSet, TreeMap, TreeSet or ArrayList, depending on the interface type.

Collections instances have the usual behavior of value types

您可以用 ArrayList 替换 HashSet

关于java - Hibernate实体生成奇怪的sql并尝试保存重复的条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8830363/

相关文章:

sql - 总结数字

mysql - 如何使用hibernate从mysql获取当前日期数据列表?

java - org.hibernate.HibernateException : Error while accessing enum. 值() : class com. mksoft.fbautomate.domain.Account$Type

java - 从许多 jar 文件创建合并的可执行 Jar(在类路径中使用)

java - Log4JLogger'找不到或不可用的根本原因是什么?

java - 选择单选按钮组时按钮未启用

java - 将 org.hibernate.jpa.HibernatePersistenceProvider 与 BoneCP 一起使用时遇到错误

java - 通过更改 URL 在 .Net Webservice 和 Java Webservice 之间切换

mysql - 将 NOT NULL 添加到 SQL 中的列

mysql - 根据不同区域的日期名称减去时间