I want to get the most recent executed ChildEntity
from a ParentEntity
based on last lastExecutionTimestamp
field. I tried the following query which does not work.
Class Relation : ParentEntity <1-oneToMany-x> ChildEntity<1-oneToMany-x>GrandChildEntity
The ChildEntity
has a field lastExecutionTimestamp
, which I want to use to the recently executed childEntity. The method is suppose to return List<ChildEntity>
with just one record in it . The childEntity should contain all the associated grandChildEntities
in it.
Any inputs ?
@Query(value = "select pr.childEntities from ParentEntity pr " + "inner join pr.childEntities ch ON pr.id = ch.parentEntity " + "inner join ch.grandChildEntities gc ON ch.id = gc.childEntity " + "where pr.bumId = ?1 and ch.lastExecutionTimestamp = ( select max(lastExecutionTimestamp) from ChildEntity)" ) List<ChildEntity> findLastExecutedChildFromBumId(@Param("bumId") String bumId);
Associated Class Entities
@Entity @Getter @Setter @Table(name = "table_parent") @RequiredArgsConstructor @NoArgsConstructor @AllArgsConstructor public class ParentEntity implements Serializable { private static final long serialVersionUID = -271246L; @Id @SequenceGenerator( name="p_id", sequenceName = "p_sequence", initialValue = 1, allocationSize = 1) @GeneratedValue(generator="p_id") @Column(name="id", updatable=false, nullable=false) private Long id; @NonNull @Column(name ="bum_id", nullable = false, unique = true) private String bumId; @NonNull @Column(nullable = false, length = 31) private String f1; @NonNull @Column(nullable = false, length = 31) private String f2; @NonNull @Column( nullable = false, length = 255) @Convert(converter = JpaConverterJson.class) private List<String> f3; @NonNull @Column(nullable = false) private String f4; @NonNull @Column(name = "es_status", nullable = false, length = 255) @Enumerated(EnumType.STRING) private ExecutionStatus esStatus; @JsonManagedReference @OneToMany(mappedBy = "parentEntity", cascade = CascadeType.ALL, fetch = FetchType.EAGER) @Setter(AccessLevel.NONE) private List<ChildEntity> childEntities; public void setChildEntities(List<ChildEntity> childEntities) { this.childEntities = childEntities; childEntities.forEach(entity -> entity.setParentEntity(this)); } } @Entity @Getter @Setter @Table(name= "table_child") @NoArgsConstructor public class ChildEntity implements Serializable { private static final long serialVersionUID = -925587271547L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @JsonBackReference @ManyToOne(fetch = FetchType.EAGER ) @JoinColumn(name = "parent_id") private ParentEntity parentEntity; @Column(name = "c1",nullable = false) @NonNull @Convert(converter = JpaConverterJson.class) private String c1; @Column(name = "last_exec_status",nullable = false) @NonNull @Enumerated(EnumType.STRING) private ExecutionStatus lastExecStatus; @Column(name = "c4",nullable = false) @NonNull private String c4; @Column(name = "last_execution_timestamp",nullable = false) @NonNull private long lastExecutionTimestamp; @JsonManagedReference @NonNull @OneToMany(mappedBy = "childEntity", cascade = CascadeType.ALL, fetch = FetchType.EAGER) @Setter(AccessLevel.NONE) private List<GrandChildEntity> grandChildEntities; public void setGrandChildEntities(List<GrandChildEntity> grandChildEntities) { this.grandChildEntities = grandChildEntities; grandChildEntities.forEach(entity -> entity.setChildEntity(this)); } } @Entity @Getter @Setter @Table(name="table_grand_child") @NoArgsConstructor //@AllArgsConstructor public class GrandChildEntity implements Serializable { private static final long serialVersionUID = -925567241248L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @JsonBackReference @ManyToOne(fetch = FetchType.EAGER ) @JoinColumn(name = "child_entity_id") private ChildEntity childEntity; @Column(name="gc1",nullable = false) private String gc1; @Column(name="gc2",nullable = false) private String gc2; @Column(name="gc3",nullable = false) private String gc3; @Column(name="gc3",nullable = true) private List<String> gc3; }
Advertisement
Answer
First of all many thanks to “SternK” for getting me to this right solution below:
Approach – 1
@Query("select ch from ChildEntity ch " + " join ch.parentEntity pr " + " join fetch ch.grandChildEntities gc " + " where pr.bumId = :bumId and ch.lastExecutionTimestamp in ( select max(ch1.lastExecutionTimestamp) from ChildEntity ch1 join ch1.grandChildEntities gc where ch1.parentEntity = pr group by ch1.c1))") List<ChildEntity> findLastExecutedChildFromBumId(@Param("bumId") String bumId);
Approach – 2
Another approach which I figured out ( executing faster ) was to create a custom “Model” class which contains the required fields you need to extract and then create a new
class of the custom model defined, like so:
@Query(value = "select new com.project.package.api.models.CustomResultModel(" + "cast(pr.bumId as java.lang.String),"+ "cast(pr.field1 as java.lang.String),"+ "cast(pr.field2 as java.lang.String),"+ "cast(ch.field1 as java.lang.String),"+ "cast(tr.field1 as java.lang.String),"+ "cast(tr.field2 as java.lang.String),"+ "cast(ch.field3 as java.lang.String),"+ "cast(ch.lastCompletedStaus as java.lang.String),"+ "cast(ch.lastExecutionTimestamp as java.lang.Long)) from ParentEntity pr" + "inner join ChildEntity ch.ON pr.id = ch.parentEntity " + "inner join GrandChildEntity tr ON ch.id = tr.childEntity " + "where pr.bumId = ?1 " + "and ch.lastExecutionTimestamp = ( select max(b.lastExecutionTimestamp) from ChildEntity b where "+ "b.parentEntity = ch.parentEntity )") List<CustomResultModel> findLastExecutedChildFromBumId(@Param("bumId") String bumId);