下面是我的产品应用程序中的一些表,我需要根据数据值执行 case 语句。
class Payment implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@JoinColumn(name = "payee_id", referencedColumnName = "id", nullable = true)
@OneToOne(optional = true)
private ProductPayee payeeId;
@JoinColumn(name = "allocation_id", referencedColumnName = "id", nullable = true)
@OneToOne(optional = true)
private ProductAllocation allocationId; // can have value only if no payeeId(ie, when payeeId = null) else null
@JoinColumn(name = "user_id", referencedColumnName = "id", nullable = true)
@OneToOne(optional = true)
private Recipient userId; // if no payeeId
@Column(name = "amount")
private Double amount;
}
class ProductPayee implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@JoinColumn(name = "allocation_id", referencedColumnName = "id", nullable = false)
@OneToOne(optional = false)
private ProductAllocation allocationId;
@JoinColumn(name = "user_id", referencedColumnName = "id", nullable = false)
@OneToOne(optional = false)
private Recipient userId;
}
class ProductAllocation implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@JoinColumn(name = "product_id", referencedColumnName = "id", nullable = false)
@OneToOne(optional = true)
private Product productId;
@Column(name = "amount")
private Double amount;
}
class GroupLink implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@JoinColumn(name = "group_id", referencedColumnName = "id", nullable = false)
@OneToOne(optional = true)
private Group groupId;
@JoinColumn(name = "product_id", referencedColumnName = "id", nullable = false)
@OneToOne(optional = false)
private Product productId;
}
class GroupStaff implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@JoinColumn(name = "staff_id", referencedColumnName = "id", nullable = false)
@OneToOne(optional = false)
private Staff staffId;
@JoinColumn(name = "group_id", referencedColumnName = "id", nullable = false)
@OneToOne(optional = true)
private Group groupId;
}
class ProductStaff implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@JoinColumn(name = "staff_id", referencedColumnName = "id", nullable = false)
@OneToOne(optional = false)
private Staff staffId;
@JoinColumn(name = "allocation_id", referencedColumnName = "id", nullable = false)
@OneToOne(optional = false)
private ProductAllocation allocationId;
@Column(name="type")
private int type;
}
收件人、员工和产品就像普通的人员和物品表。
下面是我执行以获取数据的查询,其中付款表具有带值的 payeeId 或带值的 allocationId。
因此(1)如果 payeeId 存在,则 AllocationId 将为 null 并检查 ProductPayee 中的值,或者(2)否则 AllocationId 存在,则 payeeId 将为 null 并检查 ProductAllocation 表中。
Query query = session.createQuery("FROM Payment where " +
"(case when payeeId != null then payeeId.allocationId.productId.id else allocationId.productId.id end in (SELECT productId.id from GroupLink where groupId.id in (SELECT groupId.id from GroupStaff where staffId.id = :staffId)) " +
"OR case when payeeId != null then payeeId.allocationId.id else allocationId.id end in (SELECT allocationId.id FROM ProductStaff WHERE staffId.id = :staffId and type = :resType))) " +
"order by date desc");
我需要避免两列中的 where 子句中的空值列,并在两列中查找不为空的相同值,两列中的任何一列始终具有空值。
上述 HQL 查询在执行时未提供预期结果。如何在 HQL 中避免 null 情况来正确编写它?
如果您使用 Hibernate 6.0+,我可以建议在 hql 查询中使用
UNION
子句,而不是 case
,以帮助区分必须使用的不同限制,如果 payeeId
或 allocationId
字段是否为空?我尝试使用这种方法重写您的查询,获得以下信息:
"select p from Payment p where p.payeeId is not null and p.allocationId is null and "
+ "( "
+ "p.payeeId.allocationId.productId.id in (SELECT productId.id from GroupLink where groupId.id in (SELECT groupId.id from GroupStaff where staffId.id = :staffId)) "
+ "or "
+ "p.payeeId.allocationId.id in (SELECT allocationId.id FROM ProductStaff WHERE staffId.id = :staffId and type = :resType) "
+ ")"
+ "union "
+ "select p from Payment p where p.payeeId is null and p.allocationId is not null and "
+ "( "
+ "p.allocationId.productId.id in (SELECT productId.id from GroupLink where groupId.id in (SELECT groupId.id from GroupStaff where staffId.id = :staffId)) "
+ "or "
+ "p.allocationId.id in (SELECT allocationId.id FROM ProductStaff WHERE staffId.id = :staffId and type = :resType)"
+ ")"
如您所见,有两个子查询的
union
,第一个子查询在payeeId
不为空时出现,另一个在allocationId
不为空时出现。我只是强制强制执行不为空的条件。
您在问题中说“查询在执行时未提供适当的结果”:哪些记录是丢失的,或者是在不应该返回的时候返回的?