I want to insert records from first entity to a second entity when a value of specific field of the first entity changed. For this I am trying use onAfterUpdate Listener of Entity 1 but the records are inserted twice.
Here is the listener:
@Override
public void onAfterUpdate(JournalHeader entity) {
if (entity.getPosted() == true) {
postEntries(entity);
}
}
//@Override
@Transactional
public void postEntries(JournalHeader entity) {
try (Transaction tx = persistence.createTransaction()) {
TypedQuery<JournalDetail> detailQuery = persistence.getEntityManager().createQuery("select e from mydb$JournalDetail e " +
"where e.glJournalHeader.id = ?1 ", JournalDetail.class); //and c.workShift.id = ?2 and c.capacityUnit=?3 glJournalHeader.id
detailQuery.setParameter(1, entity.getId());
List<JournalDetail> details = detailQuery.getResultList();
for (JournalDetail detail : details) {
GlAccountsBalance balance = metadata.create(GlAccountsBalance.class);
balance.setCompany(entity.getCompany());
balance.setFinancialPeriod(entity.getPeriod());
balance.setFinancialYear(entity.getFinaYear());
balance.setGlAccounts(detail.getGlAccounts());
balance.setGlAccountsSub(detail.getGlAccountsSub());
balance.setCredit(detail.getCredit());
balance.setDebit(detail.getDebit());
persistence.getEntityManager().persist(balance);
}
tx.commit();
}
}
Thanks for helping where I am making the mistake.
krivopustov
(Konstantin Krivopustov)
July 25, 2016, 6:31am
#2
Hi Mortoza,
I don’t know why you have duplicates, perhaps your detailQuery returns more results than you expected.
But I would suggest using BeforeUpdateEntityListener and do everything in a single transaction.
See for example cuba platform - Create Entity by using EntityListener - Stack Overflow
Hi Konstantin
Just tried using the BeforeUpdateEntityListener, same double records!!
the the detail entity has 2 records with reference to the header entity selected. I am expecting those two records to be inserted to the 2nd table but it is inserting 4 records.
Hi Konstantin,
Here is the codes:
Entity (Header)
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Column;
import com.haulmont.cuba.core.entity.StandardEntity;
import com.haulmont.chile.core.annotations.Composition;
import com.haulmont.cuba.core.entity.annotation.OnDelete;
import com.haulmont.cuba.core.global.DeletePolicy;
import java.math.BigDecimal;
import java.util.Set;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import com.haulmont.chile.core.annotations.NamePattern;
import java.util.Date;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import com.haulmont.cuba.core.entity.annotation.Listeners;
import java.util.List;
/**
* @author Mortoza
*/
@Listeners({"inteaccgms_JournalHeaderBean", "inteaccgms_JournalHeaderBean"})
@NamePattern("%s %s|journalNumber,description")
@Table(name = "INTEACCGMS_JOURNAL_HEADER")
@Entity(name = "inteaccgms$JournalHeader")
public class JournalHeader extends StandardEntity {
private static final long serialVersionUID = 2478827267578850775L;
@Column(name = "JOURNAL_NUMBER")
protected Long journalNumber;
@Temporal(TemporalType.DATE)
@Column(name = "TRAN_DATE", nullable = false)
protected Date tranDate;
@Column(name = "DESCRIPTION")
protected String description;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "FINA_YEAR_ID")
protected FinancialYear finaYear;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "PERIOD_ID")
protected FinancialPeriod period;
@Column(name = "TOTAL_DEBIT")
protected BigDecimal totalDebit;
@Column(name = "TOTAL_CREDIT")
protected BigDecimal totalCredit;
@Composition
@OnDelete(DeletePolicy.CASCADE)
@OneToMany(mappedBy = "glJournalHeader")
protected List<JournalDetail> journalDetail;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "CURRENCY_ID")
protected Currency currency;
@Column(name = "POSTED")
protected Boolean posted = false;
@Column(name = "READY_FOR_POSTING")
protected Boolean readyForPosting = false;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "COMPANY_ID")
protected Company company;
public List<JournalDetail> getJournalDetail() {
return journalDetail;
}
public void setJournalDetail(List<JournalDetail> journalDetail) {
this.journalDetail = journalDetail;
}
public void setCompany(Company company) {
this.company = company;
}
public Company getCompany() {
return company;
}
public FinancialPeriod getPeriod() {
return period;
}
public void setPeriod(FinancialPeriod period) {
this.period = period;
}
public void setPosted(Boolean posted) {
this.posted = posted;
}
public Boolean getPosted() {
return posted;
}
public void setReadyForPosting(Boolean readyForPosting) {
this.readyForPosting = readyForPosting;
}
public Boolean getReadyForPosting() {
return readyForPosting;
}
public void setCurrency(Currency currency) {
this.currency = currency;
}
public Currency getCurrency() {
return currency;
}
public void setTranDate(Date tranDate) {
this.tranDate = tranDate;
}
public Date getTranDate() {
return tranDate;
}
public void setFinaYear(FinancialYear finaYear) {
this.finaYear = finaYear;
}
public FinancialYear getFinaYear() {
return finaYear;
}
public void setJournalNumber(Long journalNumber) {
this.journalNumber = journalNumber;
}
public Long getJournalNumber() {
return journalNumber;
}
public void setTotalCredit(BigDecimal totalCredit) {
this.totalCredit = totalCredit;
}
public BigDecimal getTotalCredit() {
return totalCredit;
}
public void setTotalDebit(BigDecimal totalDebit) {
this.totalDebit = totalDebit;
}
public BigDecimal getTotalDebit() {
return totalDebit;
}
public void setDescription(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
Detail entity
import javax.persistence.Entity;
import javax.persistence.Table;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import com.haulmont.cuba.core.entity.StandardEntity;
import com.haulmont.chile.core.annotations.NamePattern;
/**
* @author Mortoza
*/
@NamePattern("%s |glAccounts")
@Table(name = "INTEACCGMS_JOURNAL_DETAIL")
@Entity(name = "inteaccgms$JournalDetail")
public class JournalDetail extends StandardEntity {
private static final long serialVersionUID = -4142076474086793828L;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "GL_ACCOUNTS_ID")
protected GlAccounts glAccounts;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "GL_ACCOUNTS_SUB_ID")
protected GlAccountsSub glAccountsSub;
@Column(name = "REFERENCE", length = 100)
protected String reference;
@Column(name = "DEBIT")
protected BigDecimal debit;
@Column(name = "CREDIT")
protected BigDecimal credit;
@Column(name = "EXCHANGE_RATE", precision = 19, scale = 4)
protected BigDecimal exchangeRate;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "GL_JOURNAL_HEADER_ID")
protected JournalHeader glJournalHeader;
public JournalHeader getGlJournalHeader() {
return glJournalHeader;
}
public void setGlJournalHeader(JournalHeader glJournalHeader) {
this.glJournalHeader = glJournalHeader;
}
public GlAccountsSub getGlAccountsSub() {
return glAccountsSub;
}
public void setGlAccountsSub(GlAccountsSub glAccountsSub) {
this.glAccountsSub = glAccountsSub;
}
public void setReference(String reference) {
this.reference = reference;
}
public String getReference() {
return reference;
}
public void setGlAccounts(GlAccounts glAccounts) {
this.glAccounts = glAccounts;
}
public GlAccounts getGlAccounts() {
return glAccounts;
}
public void setExchangeRate(BigDecimal exchangeRate) {
this.exchangeRate = exchangeRate;
}
public BigDecimal getExchangeRate() {
return exchangeRate;
}
public void setDebit(BigDecimal debit) {
this.debit = debit;
}
public BigDecimal getDebit() {
return debit;
}
public void setCredit(BigDecimal credit) {
this.credit = credit;
}
public BigDecimal getCredit() {
return credit;
}
}
Listener
package com.inteacc.gms.listener;
import com.haulmont.cuba.core.Persistence;
import com.haulmont.cuba.core.Transaction;
import com.haulmont.cuba.core.TypedQuery;
import com.haulmont.cuba.core.app.UniqueNumbersService;
import com.haulmont.cuba.core.global.Metadata;
import com.haulmont.cuba.core.listener.BeforeInsertEntityListener;
import com.inteacc.gms.entity.GlAccountsBalance;
import com.inteacc.gms.entity.JournalDetail;
import com.inteacc.gms.entity.JournalHeader;
import javax.inject.Inject;
import org.springframework.stereotype.Component;
import com.haulmont.cuba.core.listener.AfterUpdateEntityListener;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import com.haulmont.cuba.core.listener.BeforeUpdateEntityListener;
/**
* @author Mortoza
*/
@Component("inteaccgms_JournalHeaderBean")
public class JournalHeaderListener implements BeforeInsertEntityListener<JournalHeader>, BeforeUpdateEntityListener<JournalHeader> {
@Inject
private UniqueNumbersService unService;
@Inject
private Persistence persistence;
@Inject
private Metadata metadata;
@Override
public void onBeforeInsert(JournalHeader entity) {
entity.setJournalNumber(unService.getNextNumber("Journal_Number"));
}
@Override
public void onBeforeUpdate(JournalHeader entity) {
if (entity.getPosted() == true) {
postEntries(entity);
}
}
//@Override
@Transactional
public void postEntries(JournalHeader entity) {
try (Transaction tx = persistence.createTransaction()) {
TypedQuery<JournalDetail> detailQuery = persistence.getEntityManager().createQuery("select e from inteaccgms$JournalDetail e " +
"where e.glJournalHeader.id = ?1 ", JournalDetail.class); //and c.workShift.id = ?2 and c.capacityUnit=?3 glJournalHeader.id
detailQuery.setParameter(1, entity.getId());
List<JournalDetail> details = detailQuery.getResultList();
for (JournalDetail detail : details) {
GlAccountsBalance balance = metadata.create(GlAccountsBalance.class);
balance.setCompany(entity.getCompany());
balance.setFinancialPeriod(entity.getPeriod());
balance.setFinancialYear(entity.getFinaYear());
balance.setGlAccounts(detail.getGlAccounts());
balance.setGlAccountsSub(detail.getGlAccountsSub());
balance.setCredit(detail.getCredit());
balance.setDebit(detail.getDebit());
persistence.getEntityManager().persist(balance);
}
tx.commit();
}
}
}
krivopustov
(Konstantin Krivopustov)
July 27, 2016, 6:55am
#6
What about my suggestions?
1) Clean your BeforeUpdate listener from transaction management code, and check again. If the problem persists, provide the source code of your entities and the listener.
2) Ensure that your listener is invoked twice. Set a breakpoint in the IDE and check it.
Hi Konstantin,
I have create a sample project for this as attached. Thanks for your help in advance. Unfortunately, the is no updates done by the listener in the target entity, main entity is updated though.
Mortoza
sample-listeners.zip (529.3K)
ok, I have resolved it. thanks.
ntha792697
(Nguyen Tien Ha)
March 14, 2017, 5:39am
#9
I have the same this problem. Could you share your resolved solution?