动态joincolumn和join子句与变量

时间:2014-02-18 06:47:46

标签: sql hibernate hibernate-annotations

我有一对一的单向关系。我想要实现的是

  • 使用CASE创建一个join on子句并向其发送变量,以便我可以更改连接列(欢迎更改连接列的任何其他建议)
  • 忽略hibernate创建的第一个子句,并使用问题底部的条件创建特定的ON子句。

我的查询在SQL Manager中有效:

SELECT d.Description, d.AccountId, d.PartnerId, a.FormattedName FROM 
InvoiceDesigns d 
INNER JOIN UserAccount a
ON 
    a.id =
    CASE 
        WHEN d.PartnerId != -1 AND d.AccountId = 1 THEN d.PartnerId
        WHEN d.PartnerId = 1 THEN d.AccountId 
        ELSE 1
    END
WHERE
d.AccountId = 1 OR PartnerId = 1

工作查询在SQL Manager中运行,而不是在hibernate中运行。这是我想要实现的,我希望hibernate创建这样的查询。
当一个帐户,让我们说ID = 1坚持示例,显示他们将看到的设计
A)设计的PartnerId不是-1且AccountId为1,这意味着它是由该帐户的合作伙伴创建的,并将显示合作伙伴的formattedName。
在查看可用设计时,这适用于普通帐户。如果合作伙伴为他们创建了设计,他们将看到该合作伙伴的名称。

B) PartnerId等于帐户的ID,这意味着它是合作伙伴设计,并且将显示为其创建的帐户相关设计的formattedName。 这是合作伙伴帐户查看他们创建的设计。

C)设计由帐户直接创建,因此将显示自己的名称。对于普通帐户和自己创建的设计。

当我只想使用AccountId或PartnerId时,正常连接在hibernate中正常工作但我需要更改列以获取相关的FormattedName。我试过@ Where,@ Filter,@ JoinColumnOrFormula但是我无法实现这个查询。

我和@Where的课程基本上是这样的:

设计类:

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id")
    int id;

    @Column(name="AccountId")
        int accountId;

    @Column(name="PartnerId")
        int partnerId;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "AccountId", referencedColumnName = "id", insertable = false, updatable = false, nullable = true)
    @Where(clause = "CASE " +
                            "WHEN PartnerId != -1 AND AccountId = :accountId THEN PartnerId " +
                            "WHEN PartnerId = :accountId THEN AccountId " +
                            "ELSE :accountId " + 
                        "END")
    AccountData account;

帐户类:

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
int id;

@Column(name="FormattedName")
String formattedName;

在这里,您可以看到我想使用“:accountId”将ID作为参数进行查询,该帐户将用于定义连接列。

这个问题:custom join clause实际上做了类似的事情。这就是为什么我专注于where子句

另外:我还找到了符合标准的内容

Criteria criteria = session.createCriteria(InvoiceDesignData.class, "design");
            criteria.createCriteria("design.account", "acc", JoinType.LEFT_OUTER_JOIN, Restrictions.eqProperty("acc.id", "design.partnerId"));

            invoiceDesignList = criteria.list();

但这不会忽略第一个条件,并使用AND为ON子句添加一个附加条件。我从@ one-to-many中删除了连接列,希望忽略第一个条件,但事实并非如此。生成查询:

from InvoiceDesigns this_ left outer join UserAccount acc1_ on this_.account_id=acc1_.id and ( acc1_.id=this_.PartnerId )

提前致谢

2 个答案:

答案 0 :(得分:0)

您可以尝试移动案例陈述:

SELECT  d.Description, d.AccountId, d.PartnerId, a.FormattedName 
FROM    (SELECT *, CASE 
                WHEN PartnerId != -1 AND AccountId = 1 THEN PartnerId
                WHEN PartnerId = 1 THEN AccountId 
                ELSE 1
            END AS SmartID
         FROM InvoiceDesigns) d 
        INNER JOIN UserAccount a
        ON a.id = d.SmartID
WHERE d.AccountId = 1 OR PartnerId = 1

编辑:这基本上会让你在没有条件ON语句的情况下直接加入内联查询。

答案 1 :(得分:0)

如果您只想将每个Design映射到一个AccountData对象,只有一个连接,但您希望根据其值加入accountId或partnerId,那么您应该可以通过使用连接来实现式。你会想要这样的东西:

@ManyToOne
@JoinColumnsOrFormulas(
    { @JoinColumnOrFormula(
        formula = @JoinFormula(
         value = "case " +
                 "when partnerId != -1 and accountId = 1 then partnerId" +
                 "when partnerId = accountId then accountId " +
                 "else 1" +
                 "end", 
         referencedColumnName="id")) }
)

请注意,您需要使用@ManyToOne注释,即使这实际上是一对一关联。如果您尝试在一对一上使用它,则连接公式将不起作用。

然后,您只需使用正常的HQL连接检索数据:

SELECT d.description, d.accountId, d.partnerId, a.formattedName FROM Design d 
inner join d.account a