Hibernate: почему createAll (Batch Inserts) в Loop создает проблему, тогда как create выполняется нормально?

Родительская организация:

public class CustomerAgreement implements Serializable {
@OneToMany(mappedBy = "customerAgreement", orphanRemoval = true, fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST})
    private List<CustomerAgreementPeriod> agreementPeriods;

}

Дочерний объект

@Entity(name = "CustomerAgreementPeriod")
@Table(name = "CIM_SNOW_CUST_AGT_PERIODS_TAB")
public class CustomerAgreementPeriod  implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @SequenceGenerator(name = "CustomerAgreementPeriodSeq", sequenceName = "CIM_SNOW_CUST_AGT_PERIOD_SEQ")
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "CustomerAgreementPeriodSeq")
    @Column(name = "ID")
    private Long id;
    @ManyToOne
    @JoinColumn(name = "CUSTID")
    private CustomerAgreement customerAgreement;
    @Column(name = "PID")
    private String pid;
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "VALIDFROM")
    private Date validFrom;
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "VALIDTO")
    private Date validTo;

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public CustomerAgreement getCustomerAgreement() {
        return customerAgreement;
    }
    public void setCustomerAgreement(CustomerAgreement customerAgreement) {
        this.customerAgreement = customerAgreement;
    }
    public String getPid() {
        return pid;
    }
    public void setPid(String pid) {
        this.pid = pid;
    }
    public Date getValidFrom() {
        return validFrom;
    }
    public void setValidFrom(Date validFrom) {
        this.validFrom = validFrom;
    }
    public Date getValidTo() {
        return validTo;
    }
    public void setValidTo(Date validTo) {
        this.validTo = validTo;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((customerAgreement == null) ? 0 : customerAgreement.hashCode());
        result = prime * result + ((pid == null) ? 0 : pid.hashCode());
        result = prime * result + ((validFrom == null) ? 0 : validFrom.hashCode());
        result = prime * result + ((validTo == null) ? 0 : validTo.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        CustomerAgreementPeriod other = (CustomerAgreementPeriod) obj;
        if (customerAgreement == null) {
            if (other.customerAgreement != null)
                return false;
        } else if (!customerAgreement.equals(other.customerAgreement))
            return false;
        if (pid == null) {
            if (other.pid != null)
                return false;
        } else if (!pid.equals(other.pid))
            return false;
        if (validFrom == null) {
            if (other.validFrom != null)
                return false;
        } else if (!validFrom.equals(other.validFrom))
            return false;
        if (validTo == null) {
            if (other.validTo != null)
                return false;
        } else if (!validTo.equals(other.validTo))
            return false;
        return true;
    }


}

Когда я использую следующий метод в Dao и отправляю партию объектов:

@Override
public void createAll(Collection<T> ts) {
    if (ts == null) {
        return;
    }
    for (T t : ts) {
        LOG.info(t.toString());
        em.persist(t);
    }
}

Это дает следующее исключение.

    2019-12-04 11:32:14,295 INFO  [stdout] (EJB default - 10) Hibernate: 
2019-12-04 11:32:14,295 INFO  [stdout] (EJB default - 10)     select
2019-12-04 11:32:14,295 INFO  [stdout] (EJB default - 10)         CUST_AGT_PERIOD_SEQ.nextval 
2019-12-04 11:32:14,295 INFO  [stdout] (EJB default - 10)     from
2019-12-04 11:32:14,295 INFO  [stdout] (EJB default - 10)         dual
2019-12-04 11:32:14,297 ERROR [org.jboss.as.ejb3.invocation] (EJB default - 10) WFLYEJB0034: EJB Invocation failed on component CustomerAgreementDaoImpl for method public abstract void com.evry.integrator.snow.model.dao.GenericDao.createAll(java.util.Collection): javax.ejb.EJBTransactionRolledbackException: A different object with the same identifier value was already associated with the session : [com.evry.integrator.snow.model.CustomerAgreementPeriod#-35]

Когда я создаю, используя следующее для одного объекта

@Override
public T create(final T t) {
    LOG.info(t.toString());
    this.em.persist(t);
    return t;
}

Работает нормально.

List<CustomerAgreement> currentBatch = customerAgreement.subList(offset, Math.min(offset+itemsPerBatch, customerAgreement.size()));
customerAgreementDaoImpl.createAll(currentBatch);
customerAgreementDaoImpl.flush();

Может ли кто-нибудь помочь, как это сделать в пакетной операции с помощью createAll?

Также удивительно то, что с помощью create он создает последовательность с -33?

1 ответ

Это было исправлено установкой свойства в persistance.xml.

<property name="hibernate.id.new_generator_mappings" value="false" />       

а также изменил GenerationStrategy с

 GenerationType.AUTO to GenerationType.Sequence

Не уверены, что это хороший способ сделать это?

Другие вопросы по тегам