3

TL:博士;

具有外键约束的 CF ORM 组件的正确语法/解决方法/hack 是什么?


ColdFusion + 整数

将变量存储为整数应该是一个简单的编程问题,对吧?在语言的文档中找到适当的函数(如果你不能从圆顶上回忆它),它会说返回:int(owtte)并使用它。

不使用 ColdFusion。

你们中的一些人可能已经意识到 ColdFusion 的各种整数问题,但目前导致我快速脱发的一个问题是,ColdFusion 有时会将您的“整数”存储为字符串、double 或 long。现在,对于大多数用例来说,这不是一个破坏功能的问题,并且经常被忽视/忽略/未被发现。就我而言,例外情况是 ORM 发挥作用的时候。当然,就像任何明智的开发人员一样,我认识到这可能是由于某处的用户错误造成的。


问题

每当 CF 尝试与数据库交互时,就会出现此问题。如果有一个字段是外键并且类型为“整数”,CF 会抛出 Hibernate Exception 并显示以下消息:

java.lang.Integer

而已。有帮助,对吧?我发现这个“错误消息”明确地是您传递到该字段的变量类型,因此如果您错误地将双精度传递到该字段,错误消息将显示为java.lang.Double.

现在,这似乎与字段本身无关,而与相关组件有关 - 这仅发生在具有将其链接到其他地方的整数字段的外键约束的字段上。

我要做的事情的基本示例:

模板.cfc

component persistent="true" table="template"{

    property name="id"              type="numeric"  sqltype="integer"   column="templateID" fieldtype="id"  generator="identity";
    property name="userID"          type="numeric"  sqltype="integer"   fkcolumn="userID"           fieldtype="many-to-one" cfc="User";
    property name="lastModified"    type="date"     sqltype="timestamp" column="lastModified";

}

用户.cfc

component persistent="true" table="user"{

    property name="id"          type="numeric"  sqltype="integer"   column="userID"     fieldtype="id" generator="identity";
    property name="username"    type="string"   sqltype="nvarchar"  column="username";
    property name="password"    type="string"   sqltype="nvarchar"  column="password";

}

刷新已更新的 ORM 时会出现问题template.userID


我尝试过的事情

  • 联系 Adob​​e CF 支持(我们有一个企业许可证和白金支持,但在一个月内他们无法给我解决方案,甚至除了“它不起作用?”之外的任何信息)
  • ormtype属性添加到身份字段(然后在不起作用时添加外键字段)
  • 更改sqltype属性(我现在认为这仅用于创建表,因为数据库已经到位,所以我们从来不需要)
  • 使用以下函数的各种组合转换变量:
    • NumberFormat( var )- 文档说它返回“一个格式化的数值”,实际上返回一个java.lang.String
    • LSParseNumber( var )- 返回一个双精度
    • Int( var )- 这个很棒:文档说它返回一个integer,作为一个string。实际上返回一个java.lang.Double
    • Val( var )- 返回一个双精度
    • javaCast( 'int', var )- 返回一个整数,它会抛出相同的错误
  • 在属性上设置elementtype属性(两端)
  • validate将属性(两端)的属性放宽为“数字”

我怀疑这可能与 Hibernate 和 CF 的组合有关,而不仅仅是 CF,尽管它让人想起 javascript 的怪癖,但我仍然喜欢它。


环境

  • 视窗服务器 2012 R2
  • ColdFusion 2016(企业版)
  • SQL 服务器
4

1 回答 1

0

TL:博士;

传递实体,而不是 ID。CF ORM 中引用持久实体 Foo 的外键属性是 Foo 类型而不是 int。

更多详情

经过这么长时间,Adobe 让我绕过了几个人,直到我找到了一位知道他在说什么的工程师。事实证明,问题不在于 ORM 引擎(Hibernate)没有将整数识别为整数,而是如果您有一个引用另一个持久实体的外键,那么您必须传递实体而不是 ID。

示例(在问题的上下文中)

首先,我从问题中删除了typeand值,因为前者可以通过 CF 检查数据库来检索(在我的情况下这很好,但您可能必须明确设置它,特别是如果您已在 Application 中sqltype关闭useDBforMapping.cfc)。

其次,我已将userIDTemplate 组件中的属性重命名为user,因为它可以帮助那些没有立即理解我上面所说的“传递实体”的人更好地对其进行可视化。

模板.cfc

component persistent="true" table="template"{

    property name="id"              column="templateID"      fieldtype="id"          generator="identity";
    property name="user"            fkcolumn="userID"        fieldtype="many-to-one" cfc="User";
    property name="lastModified"    column="lastModified";

}

用户.cfc

component persistent="true" table="user"{

    property name="id"          column="userID"     fieldtype="id" generator="identity";
    property name="username"    column="username";
    property name="password"    column="password";

}

因此,假设您知道与此模板关联的用户的 ID(例如,他们可能是创建者)。您要做的是,不要将 ID 传递给user属性,而是创建一个 User 组件,然后.

索引.cfm

userID = 4; // Example user ID, which we got from somewhere earlier in the code

templateID = 20; // Example template ID, which we got from somewhere earlier in the code

// Create template entity (loading by primary key)
template = EntityLoadByPK( 'Template', templateID );

// To set the user in the Template entity, we must pass a User entity
user = EntityLoadByPK( 'User', userID );

// Only then can we successfully update the template's foreign key property
template.setUser( user );
EntitySave( template );

// Line below is not usually needed, but it forces DB interaction so it's 
// useful in the context of this example
ORMFlush();

希望这可以帮助遇到同样困惑的其他人。

JC

于 2017-08-31T14:52:47.133 回答