Hibernate 选择最近执行的子实体
Hibernate selecting a recent executed child entity
我想根据最后一个 lastExecutionTimestamp
字段从 ParentEntity
中获取最近执行的 ChildEntity
。我尝试了以下无效的查询。
Class 关系:ParentEntity <1-oneToMany-x> ChildEntity<1-oneToMany-x>GrandChildEntity
ChildEntity
有一个字段 lastExecutionTimestamp
,我想将其用于最近执行的 childEntity。该方法假设 return List<ChildEntity>
其中只有一条记录。 childEntity 应包含所有关联的 grandChildEntities
。
有任何输入吗?
@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);
关联 Class 个实体
@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;
}
尝试使用以下查询:
@Query("select ch from ChildEntity ch "
+ " join ch.parentEntity pr "
+ " join fetch ch.grandChildEntities gc "
+ " where pr.bumId = :bumId and ch.lastExecutionTimestamp = ( select max(ch1.lastExecutionTimestamp) from ChildEntity ch1 where ch1.parentEntity = pr)")
List<ChildEntity> findLastExecutedChildFromBumId(@Param("bumId") String bumId);
首先非常感谢“SternK”让我得到下面这个正确的解决方案:
方法 - 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);
方法 - 2
我想出的另一种方法(执行速度更快)是创建一个自定义“模型”class,其中包含您需要提取的必填字段,然后创建一个 new
class 定义的自定义模型,如下所示:
@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);
我想根据最后一个 lastExecutionTimestamp
字段从 ParentEntity
中获取最近执行的 ChildEntity
。我尝试了以下无效的查询。
Class 关系:ParentEntity <1-oneToMany-x> ChildEntity<1-oneToMany-x>GrandChildEntity
ChildEntity
有一个字段 lastExecutionTimestamp
,我想将其用于最近执行的 childEntity。该方法假设 return List<ChildEntity>
其中只有一条记录。 childEntity 应包含所有关联的 grandChildEntities
。
有任何输入吗?
@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);
关联 Class 个实体
@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;
}
尝试使用以下查询:
@Query("select ch from ChildEntity ch "
+ " join ch.parentEntity pr "
+ " join fetch ch.grandChildEntities gc "
+ " where pr.bumId = :bumId and ch.lastExecutionTimestamp = ( select max(ch1.lastExecutionTimestamp) from ChildEntity ch1 where ch1.parentEntity = pr)")
List<ChildEntity> findLastExecutedChildFromBumId(@Param("bumId") String bumId);
首先非常感谢“SternK”让我得到下面这个正确的解决方案:
方法 - 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);
方法 - 2
我想出的另一种方法(执行速度更快)是创建一个自定义“模型”class,其中包含您需要提取的必填字段,然后创建一个 new
class 定义的自定义模型,如下所示:
@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);