具有外键约束的CF ORM组件的正确语法/变通方法/破解是什么?
将变量存储为整数应该是一个简单的编程问题,对吧?在语言文档中找到适当的函数(如果你无法从圆顶上回忆起来),它会说返回:int (owtte)并使用它。
不是ColdFusion。
你们中的一些人可能已经知道ColdFusion的various issues with integers但是目前导致我快速掉头发的是ColdFusion有时将你的“整数”存储为字符串,双精度或长整数。现在,对于大多数用例而言,这不是一个功能破坏问题,而且往往被忽视/忽略/未被发现。在我的例子中,例外是ORM发挥作用。当然,正如任何敏感的开发人员所做的那样,我认识到这可能会导致用户出错。
只要CF尝试与数据库交互,就会出现问题。如果有一个字段是外键并且键入'integer',CF会抛出一个Hibernate异常,并显示以下消息:
java.lang.Integer
就是这样。有帮助,对吗?我发现这个“错误消息”显然是你传入该字段的变量类型,所以如果你错误地将一个double传递给字段,那么错误消息会显示为java.lang.Double
。
现在,这似乎不是关于字段本身,而是与相关组件有关 - 这只发生在具有外键约束的字段上,将其链接到其他地方的整数字段。
我想要的那种事情的基本例子:
Template.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";
}
User.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";
}
刷新已更新template.userID
的ORM时会出现问题。
ormtype
属性添加到标识字段(然后在不起作用时添加外键字段)sqltype
属性(我现在认为is only for table creation,因为数据库已经存在,我们从未需要这些属性)NumberFormat( var )
- 文档说它返回'格式化数字值',实际上返回java.lang.String
LSParseNumber( var )
- 返回双Int( var )
- 这个很棒:文档说它返回整数,作为字符串。实际上会返回java.lang.Double
Val( var )
- 返回双javaCast( 'int', var )
- 返回一个引发相同错误的整数elementtype
属性(两端)validate
属性(两端)放宽为“数字”我怀疑这个可能与Hibernate和CF的组合,而不仅仅是CF,并且发现它是javascript-回忆的怪癖,我仍然喜欢它。
非常感谢任何和所有帮助。
由于
JC
答案 0 :(得分:0)
传递实体,而不是ID。 引用持久性实体Foo的CF ORM中的外键属性是Foo类型而不是int。
经过这么长时间,Adobe让我绕过几个人,直到我找到了一位知道他在说什么的工程师。事实证明问题不在于ORM引擎(Hibernate)没有将整数识别为整数,但是如果你有一个引用另一个持久实体的外键,那么你必须传递实体而不是身份证。
首先,我从问题中删除了type
和sqltype
值,因为前者可以通过CF检查数据库来检索(在我的情况下很好,但你可能需要明确设置它,特别是如果你在Application.cfc中关闭了useDBforMapping
。
其次,我已将模板组件中的userID
属性重命名为user
,因为它可能会帮助那些不能立即理解我上面所说的'传递实体'以进行可视化的内容它更好。
<强> Template.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";
}
<强> User.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组件,然后传递那个。
<强> index.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