Error when loading collection with deleted entities
jviso Apr 6, 2017 7:47 AMHi everyone,
We are trying to get the full data from an entity and its related entities in a certain date. And the problem is that we get an error when accessing items from a collection that were deleted after that moment.
So it seems the problem is because is accessing to DB to retrieve entities that doesn't exist anymore.
This is the main entity:
@XmlType @XmlRootElement @Entity @Audited @Table(name = PayrollEntity.TABLE_NAME) @NamedQueries({ @NamedQuery(name = PayrollEntity.EXISTS_BY_ID_QUERY_NAME, query = PayrollEntity.EXISTS_BY_ID_QUERY, hints = {@QueryHint(name = "org.hibernate.cacheable", value = "true")}), @NamedQuery(name = PayrollEntity.FIND_PAYROLL_QUERY_NAME, query = PayrollEntity.FIND_PAYROLL_QUERY, hints = {@QueryHint(name = "org.hibernate.cacheable", value = "true")}), @NamedQuery(name = PayrollEntity.FIND_EXTRAPAY_QUERY_NAME, query = PayrollEntity.FIND_EXTRAPAY_QUERY, hints = {@QueryHint(name = "org.hibernate.cacheable", value = "true")}), @NamedQuery(name = PayrollEntity.FIND_PAYROLLS_BY_EMPLOYMENT_QUERY_NAME, query = PayrollEntity.FIND_PAYROLLS_BY_EMPLOYMENT_QUERY, hints = {@QueryHint(name = "org.hibernate.cacheable", value = "true")}), }) public class PayrollEntity extends AbstractEntity { private static final long serialVersionUID = -1982937254314630067L; /* PARAMS */ public static final String EXISTS_PAYROLL_EXCLUDEDIDPAYROLL_PARAM = "idPayroll"; public static final String EXISTS_PAYROLL_IDPAYROLLTYPE_PARAM = "idPayrollType"; public static final String EXISTS_PAYROLL_IDEMPLOYMENT_PARAM = "idEmployment"; public static final String EXISTS_PAYROLL_YEAR_PARAM = "year"; public static final String EXISTS_PAYROLL_MONTH_PARAM = "month"; public static final String EXISTS_PAYROLL_IDEXTRAPAY_PARAM = "idExtraPay"; /* QUERIES */ public static final String EXISTS_BY_ID_QUERY_NAME = "EXISTS_PAYROLL_BY_ID"; public static final String EXISTS_BY_ID_QUERY = "SELECT e.idPayroll FROM PayrollEntity e WHERE e.idPayroll = :" + EXISTS_BY_ID_QUERY_PARAM; public static final String FIND_PAYROLL_QUERY_NAME = "EXISTS_PAYROLL_BY_CONCEPTUAL_ID"; public static final String FIND_PAYROLL_QUERY = "SELECT e FROM PayrollEntity e WHERE e.idPayroll != :" + EXISTS_PAYROLL_EXCLUDEDIDPAYROLL_PARAM + " AND e.employment.idEmployment = :" + EXISTS_PAYROLL_IDEMPLOYMENT_PARAM + " AND e.year = :" + EXISTS_PAYROLL_YEAR_PARAM + " AND e.month = :" + EXISTS_PAYROLL_MONTH_PARAM + " AND e.payrollType.idPayrollType = :" + EXISTS_PAYROLL_IDPAYROLLTYPE_PARAM; public static final String FIND_EXTRAPAY_QUERY_NAME = "EXISTS_EXTRAPAY_BY_CONCEPTUAL_ID"; public static final String FIND_EXTRAPAY_QUERY = "SELECT e FROM PayrollEntity e WHERE e.idPayroll != :" + EXISTS_PAYROLL_EXCLUDEDIDPAYROLL_PARAM + " AND e.employment.idEmployment = :" + EXISTS_PAYROLL_IDEMPLOYMENT_PARAM + " AND e.year = :" + EXISTS_PAYROLL_YEAR_PARAM + " AND e.month = :" + EXISTS_PAYROLL_MONTH_PARAM + " AND e.payrollType.idPayrollType = :" + EXISTS_PAYROLL_IDPAYROLLTYPE_PARAM + " AND e.extraPay.idExtraPay = :" + EXISTS_PAYROLL_IDEXTRAPAY_PARAM; public static final String FIND_PAYROLLS_BY_EMPLOYMENT_QUERY_NAME = "FIND_PAYROLLS_BY_EMPLOYMENT"; public static final String FIND_PAYROLLS_BY_EMPLOYMENT_QUERY = "SELECT e FROM PayrollEntity e WHERE e.employment.idEmployment = :" + EXISTS_PAYROLL_IDEMPLOYMENT_PARAM + " AND e.year = :" + EXISTS_PAYROLL_YEAR_PARAM + " AND e.month = :" + EXISTS_PAYROLL_MONTH_PARAM; /* TABLE */ public static final String TABLE_NAME = "EP_PAYROLL"; /* COLUMNS */ public static final String ID_PAYROLL_COLUMN = "ID_PAYROLL"; public static final String VERSION_COLUMN = "VERSION"; public static final String ID_EMPLOYMENT_COLUMN = "ID_EMPLOYMENT"; public static final String ID_PAYROLL_TYPE_COLUMN = "ID_PAYROLL_TYPE"; public static final String YEAR_COLUMN = "YEAR"; public static final String MONTH_COLUMN = "MONTH"; public static final String CALCULATION_DATETIME_COLUMN = "CALCULATION_DATETIME"; public static final String PAYSLIP_GENERATION_DATETIME_COLUMN = "PAYSLIP_GENERATION_DATETIME"; public static final String ID_EXTRA_PAY_COLUMN = "ID_EXTRA_PAY"; public static final String DISCOUNT_RATE_CALCULATED = "DISCOUNT_RATE_CALCULATED"; public static final String DISCOUNT_RATE_SOLICITED = "DISCOUNT_RATE_SOLICITED"; public static final String DISCOUNT_RATE_APPLIED = "DISCOUNT_RATE_APPLIED"; private String idPayroll; private int version; private PayrollTypeEntity payrollType; private EmploymentEntity employment; private int year; private int month; private DateTime calculationDateTime; private DateTime payslipGenerationDatetime; private List<PayrollSalaryItemEntity> payrollSalaryItems; private ExtraPayEntity extraPay; private Float discountRateCalculated; private Float discountRateSolicited; private Float discountRateApplied; @Column(name = CALCULATION_DATETIME_COLUMN) @Type(type = JODA_DATE_TIME_JPA_CONVERTER) public DateTime getCalculationDateTime() { return calculationDateTime; } @Column(name = DISCOUNT_RATE_APPLIED, columnDefinition = "decimal(4,2)") public Float getDiscountRateApplied() { return discountRateApplied; } @Column(name = DISCOUNT_RATE_CALCULATED, columnDefinition = "decimal(4,2)") public Float getDiscountRateCalculated() { return discountRateCalculated; } @Column(name = DISCOUNT_RATE_SOLICITED, columnDefinition = "decimal(4,2)") public Float getDiscountRateSolicited() { return discountRateSolicited; } @ManyToOne(targetEntity = EmploymentEntity.class) @JoinColumn(name = ID_EMPLOYMENT_COLUMN, referencedColumnName = EmploymentEntity.ID_EMPLOYMENT_COLUMN) public EmploymentEntity getEmployment() { return employment; } @ManyToOne(targetEntity = ExtraPayEntity.class) @JoinColumn(name = ID_EXTRA_PAY_COLUMN, referencedColumnName = ExtraPayEntity.ID_EXTRA_PAY_COLUMN) public ExtraPayEntity getExtraPay() { return extraPay; } @Column(name = ID_PAYROLL_COLUMN, nullable = false, updatable = false, length = 36) @Id @GeneratedValue(generator = UUID_GENERATOR_NAME) @GenericGenerator(name = UUID_GENERATOR_NAME, strategy = UUID_GENERATOR_STRATEGY) public String getIdPayroll() { return idPayroll; } @Column(name = MONTH_COLUMN) public int getMonth() { return month; } @OneToMany(mappedBy = "payroll", cascade = CascadeType.ALL, orphanRemoval = true) public List<PayrollSalaryItemEntity> getPayrollSalaryItems() { return payrollSalaryItems; } @Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED) @ManyToOne(targetEntity = PayrollTypeEntity.class) @JoinColumn(name = ID_PAYROLL_TYPE_COLUMN, referencedColumnName = PayrollTypeEntity.ID_PAYROLL_TYPE_COLUMN) public PayrollTypeEntity getPayrollType() { return payrollType; } @Column(name = PAYSLIP_GENERATION_DATETIME_COLUMN) @Type(type = JODA_DATE_TIME_JPA_CONVERTER) public DateTime getPayslipGenerationDatetime() { return payslipGenerationDatetime; } @Version public int getVersion() { return version; } @Column(name = YEAR_COLUMN) public int getYear() { return year; } public void setCalculationDateTime(DateTime calculationDate) { this.calculationDateTime = calculationDate; } public void setDiscountRateApplied(Float discountRateApplied) { this.discountRateApplied = discountRateApplied; } public void setDiscountRateCalculated(Float discountRateCalculated) { this.discountRateCalculated = discountRateCalculated; } public void setDiscountRateSolicited(Float discountRateSolicited) { this.discountRateSolicited = discountRateSolicited; } public void setEmployment(EmploymentEntity employment) { this.employment = employment; } public void setExtraPay(ExtraPayEntity extraPay) { this.extraPay = extraPay; } public void setIdPayroll(String idPayroll) { this.idPayroll = idPayroll; } public void setMonth(int month) { this.month = month; } public void setPayrollSalaryItems(List<PayrollSalaryItemEntity> payrollSalaryItems) { this.payrollSalaryItems = payrollSalaryItems; } public void setPayrollType(PayrollTypeEntity payrollType) { this.payrollType = payrollType; } public void setPayslipGenerationDatetime(DateTime payslipGenerationDatetime) { this.payslipGenerationDatetime = payslipGenerationDatetime; } public void setVersion(int version) { this.version = version; } public void setYear(int year) { this.year = year; } }
This is the code we use to get the data from envers:
public PayrollEntity findHistorical(String idPayroll, DateTime date) { AuditReader reader = AuditReaderFactory.get(getEntityManager()); return reader.find(PayrollEntity.class, idPayroll, (int) reader.createQuery() .forRevisionsOfEntity(PayrollEntity.class, false, true) .add(AuditEntity.revisionProperty("revTimestamp").lt(date.getMillis())) .addProjection(AuditEntity.revisionNumber().max()) .add(AuditEntity.id().eq(idPayroll)) .getSingleResult()); }
Then we try to map the data to a DTO using dozer, and we get this error:
Caused by: javax.persistence.EntityNotFoundException: Unable to find es.gc.epsilon.core.domain.SalaryItemEntity with id 15 at org.hibernate.ejb.Ejb3Configuration$Ejb3EntityNotFoundDelegate.handleEntityNotFound(Ejb3Configuration.java:157) [hibernate-entitymanager-4.2.14.SP1-redhat-1.jar:4.2.14.SP1-redhat-1] at org.hibernate.proxy.AbstractLazyInitializer.checkTargetState(AbstractLazyInitializer.java:262) [hibernate-core-4.2.14.SP1-redhat-1.jar:4.2.14.SP1-redhat-1] at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:176) [hibernate-core-4.2.14.SP1-redhat-1.jar:4.2.14.SP1-redhat-1] at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286) [hibernate-core-4.2.14.SP1-redhat-1.jar:4.2.14.SP1-redhat-1] at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185) [hibernate-core-4.2.14.SP1-redhat-1.jar:4.2.14.SP1-redhat-1]
As I said, it seems it's because dozer access to a deleted item from the payrollSalaryItems collection List<PayrollSalaryItemEntity> from the main entity.
So, the question is. It's possible to map data from an entity containint deleted items in a collection to a DTO? Are we doing on the right way?
PD: we are using the Hibernate version 4.2.21.Final
Thanks in advance.