Code: Select all
@Data
@Accessors(chain = true)
@Builder
@Entity
@FieldDefaults(level = AccessLevel.PRIVATE)
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "refund_initiates")
public class RefundInitiate extends BaseEntityV3 {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Integer id;
// ... other fields
@OneToMany(mappedBy = "refundInitiate", cascade = CascadeType.ALL, orphanRemoval = true)
List refundLedgers = new ArrayList();
}
< /code>
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "refund_ledger")
@Entity
@Builder
public class AutomatedRefundLedger extends BaseEntityV3 {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Integer id;
// ... Other Fields
@ManyToOne
@JoinColumn(name = "refund_initiate_id", nullable = false)
RefundInitiate refundInitiate;
}
< /code>
As you see both are extending a base entity BaseEntityV3, this is an abstract class for audit purpose:
@Getter
@Setter
@ToString
@FieldDefaults(level = AccessLevel.PRIVATE)
@AllArgsConstructor
@NoArgsConstructor
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntityV3 {
@CreatedBy
@Column(name = "created_by")
Integer createdBy;
@CreatedDate
@Column(name = "created_on")
Date createdOn;
@LastModifiedBy
@Column(name = "updated_by")
Integer updatedBy;
@LastModifiedDate
@Column(name = "updated_on")
Date updatedOn;
@Column(name = "is_deleted")
Boolean deleted = Boolean.FALSE;
}
< /code>
This class is using @CreatedBy, @LastModifiedDate and other JPA Audit annotations.
Below we have AuditorAwareConfig
Code: Select all
@Configuration
@EnableJpaAuditing(auditorAwareRef = "userIdAuditorProvider")
public class AuditorAwareConfig {
@Bean(name = "userIdAuditorProvider")
public AuditorAware userIdAuditorProvider() {
return new AuditorAwareImpl();
}
}
@Component
class AuditorAwareImpl implements AuditorAware {
@Autowired
EmployeeRepository employeeRepo;
@Override
public Optional getCurrentAuditor() {
try {
final Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return Optional.of((principal instanceof UserDetails)
? this.getEmployeeId(((UserDetails) principal).getUsername())
: 1);
} catch (Exception e) {
return Optional.of(1);
}
}
private Integer getEmployeeId(String username) {
// TODO: Remove TEST CODE
return employeeRepo.findFirstByUsername(username).map(Employee::getId).orElse(1);
}
}
< /code>
Now here's the issue:
public AutomatedRefundLedger updateAutomatedRefundLedger(AutomatedRefundLedgerReq updateReq) {
AutomatedRefundLedger existingLedger = automatedRefundLedgerRepo.findById(updateReq.getId()).orElseThrow();
// Updates the fields of existingLedger (doesnt save it in DB)
this.updateFieldOfExistingLedger(existingLedger, updateReq);
// Saving the changes: This is where I get the error
return automatedRefundLedgerRepo.save(existingLedger);
}
< /code>
While saving the change I get error saying that:
[Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: Found shared references to a collection: payments.module.data.model.RefundInitiate.refundLedgers; nested exception is org.hibernate.HibernateException: Found shared references to a collection: payments.module.data.model.RefundInitiate.refundLedgers] with root cause
org.hibernate.HibernateException: Found shared references to a collection: payments.module.data.model.RefundInitiate.refundLedgers
< /code>
If I remove the JPA audit annotation like @CreatedBy, @CreatedDate, @LastModifiedBy and @LastModifiedDate, then it will work fine, also if I remove the extend BaseEntityV3
Code: Select all
id 'org.springframework.boot' version '2.3.4.RELEASE'