当列值不为空时如何检查多列中任意列中的属性

问题描述 投票:0回答:1

下面是我的产品应用程序中的一些表,我需要根据数据值执行 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 情况来正确编写它?

java hibernate hql
1个回答
0
投票

如果您使用 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
不为空时出现。我只是强制强制执行不为空的条件。

您在问题中说“查询在执行时未提供适当的结果”:哪些记录是丢失的,或者是在不应该返回的时候返回的?

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.