1

我正在尝试将 where 子句添加到我在其中一个对象中定义的多对多属性。我一定是做错了什么,因为我不断收到休眠错误,说该列不存在。

在模板cfc中:

<cfproperty
    name="Settings"
    fieldtype="many-to-many"
    cfc="Setting"
    linktable="settings_templates"
    fkcolumn="templateID"
    inversejoincolumn="settingsId"
    where="deleted='false'"
>

在设置cfc中:

<cfproperty
    name="templates"
    fieldtype="many-to-many"
    cfc="Template"
    linktable="settings_templates"
    fkcolumn="settingsId"
    inversejoincolumn="templateID"
    where="deleted='false'"
>

我得到的错误是:

08/02 16:06:27 [jrpp-170] 休眠错误 - [Macromedia][SQLServer JDBC 驱动程序][SQLServer]无效的列名“已删除”。

谁能看到我做错了什么?两个表中都有一个已删除的列,但链接表中没有。

4

2 回答 2

1

where多对多的属性行为非常奇怪......

为了调试这个,激活 Hibernate logging is primordial。请参考这篇文章:http ://www.rupeshk.org/blog/index.php/2009/07/coldfusion-orm-how-to-log-sql/

举个例子:

文章.cfc

/**
 * @output false
 * @persistent true
 * @table article
 */
component {

    property name="id" fieldtype="id";
    property name="title";

    property 
        name="tags" singularname="tag" 
        fieldtype="many-to-many" cfc="Tag" linktable="link_article_tag" fkcolumn="articleId" 
        inversejoincolumn="tagId" where=" deleted = 0 "
    ;

}

标记.cfc

/**
 * @output false
 * @persistent true
 * @table tag
 */
component {

    property name="id" fieldtype="id";
    property name="name";
    property name="deleted" dbdefault="0";

    property 
        name="articles" singularname="article" 
        fieldtype="many-to-many" cfc="Article" linktable="link_article_tag" fkcolumn="tagId" 
        inversejoincolumn="articleId"
    ;

}

当我尝试列出所有这样的文章时ormExecuteQuery('from Article'),请查看休眠日志中附加的内容:

select
    tags0_.articleId as articleId6_1_,
    tags0_.tagId as tagId1_,
    tag1_.id as id0_0_,
    tag1_.name as name0_0_,
    tag1_.deleted as deleted0_0_ 
from
    link_article_tag tags0_ 
inner join
    tag tag1_ 
        on tags0_.tagId=tag1_.id 
where
    tags0_.deleted = 0 

该死!WTF :| tags0_ == join table ... 你看到什么问题了吗?

为了理解这种行为,我将在 Application.cfc 中激活 HBMXML 生成,this.ormSettings.saveMapping = true 文件如下:

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                                   "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class entity-name="Tag" lazy="true"
        name="cfc:www.app.models.test.Tag" table="tag">
        <id name="id" type="string">
            <column length="255" name="id"/>
        </id>
        <property name="name" type="string">
            <column name="name"/>
        </property>
        <property name="deleted" type="string">
            <column default="0" name="deleted"/>
        </property>
        <bag name="articles" table="link_article_tag">
            <key column="tagId"/>
            <many-to-many class="cfc:www.app.models.test.Article" column="articleId"/>
        </bag>
    </class>
</hibernate-mapping>

我们可以看到:where属性是在baglevel 上设置的,而不是在 to 上many-to-many。如果我这样编辑:

    <bag name="tags" table="link_article_tag">
        <key column="articleId"/>
        <many-to-many class="cfc:www.app.models.test.Tag" column="tagId" where=" deleted = 0 "/>
    </bag>

生成的 SQL 变为:

select
    tags0_.articleId as articleId62_1_,
    tags0_.tagId as tagId1_,
    tag1_.id as id59_0_,
    tag1_.name as name59_0_,
    tag1_.deleted as deleted59_0_ 
from
    link_article_tag tags0_ 
inner join
    tag tag1_ 
        on tags0_.tagId=tag1_.id 
where
    tag1_.deleted = 0 

此方法有效,但不利于代码维护和可读性。如果有人有更好的解决方案,我很感兴趣。

于 2012-08-02T08:59:01.897 回答
1

到目前为止,我发现解决此问题的唯一方法是使用ORMExecuteQuery(). 在那里我可以直接查询对象并查找诸如此类的内容。就个人而言,我更喜欢在 cfscript 中工作,所以我的代码看起来像这样:

public array function getSettings() {
    return ORMExecuteQuery("SELECT s FROM template t JOIN t.settings s WHERE t.id=:id AND s.deleted=:deleted", {
        deleted=false, id=this.getId()
    });
}

NB – 未测试的示例

当然,您不必我一样使用参数,您可以使用deleted=false,但这取决于您(我个人喜欢使用参数)。

另外,不要忘记singularName多对多属性的属性。

在相关说明中,我在使用两个对象的属性时遇到了问题。在这种情况下,您实际上只需要在模板对象上使用它们。这样想:模板需要知道它的设置,但设置不需要知道它们所属的模板——以这种方式在两个对象上使用属性可能会导致错误,在某些情况下。

于 2014-04-02T19:22:36.450 回答