如何使用 ColdFusion ORM 存储整数?
How do I store an integer using ColdFusion ORM?
TL:DR;
具有外键约束的 CF ORM 组件的正确 syntax/workaround/hack 是什么?
ColdFusion + 整数
将变量存储为整数应该是一个简单的编程问题,对吧?在该语言的文档中找到适当的函数(如果您不记得它),它会说 returns: int (owtte) 并使用它。
不适用于 ColdFusion。
有些人可能已经知道 ColdFusion 的 various issues with integers,但目前导致我快速脱发的是 ColdFusion 有时会将您的 "integer" 存储为字符串、双精度或长。现在,对于大多数用例来说,这不是一个破坏功能的问题,而且通常是 overlooked/ignored/undiscovered。就我而言,例外情况是 ORM 开始发挥作用时。当然,就像任何明智的开发人员一样,我认识到这可能归结为某处的用户错误。
问题
只要 CF 尝试与 DB 交互,就会出现问题。如果有一个字段是外键并且类型为 'integer',CF 将抛出一个 Hibernate 异常并显示以下消息:
java.lang.Integer
就是这样。有帮助,对吧?我发现这个 "error message" 明确是您传递给该字段的变量类型,因此如果您错误地将双精度传递给该字段,错误消息将显示为 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";
}
刷新已更新的 ORM 时出现问题 template.userID
。
我尝试过的事情
- 联系 Adobe CF 支持(我们有白金支持的企业许可证,但在一个月内他们无法给我一个解决方案甚至 "it's not working?" 以外的任何信息)
- 将
ormtype
属性添加到标识字段(然后在不起作用时添加外键字段)
- 更改
sqltype
属性(我现在相信 is only for table creation 因为数据库已经就位,我们从来不需要它)
- 使用以下函数的各种组合转换变量:
NumberFormat( var )
- 文档说 returns 'A formatted number value',实际上 returns 一个 java.lang.String
LSParseNumber( var )
- returns一个双
Int( var )
- 这个很棒:文档说它 returns 一个 整数 ,作为一个 字符串 。实际上returns一个java.lang.Double
Val( var )
- returns 双
javaCast( 'int', var )
- returns 一个整数,抛出相同的错误
- 在 属性 上设置
elementtype
属性(两端)
- 放宽属性(两端)上的
validate
属性为'numeric'
我怀疑这可能与 Hibernate 和 CF 的组合有关,而不仅仅是 CF,尽管它是 javascript- 令人怀念的怪癖,但我仍然喜欢它。
环境
- Windows 服务器 2012 R2
- ColdFusion 2016(企业版)
- SQL 服务器
TL:DR;
传递实体,而不是 ID。
引用持久实体 Foo 的 CF ORM 中的外键 属性 是 Foo 类型而不是 int。
更多详情
经过这么长时间,Adobe 让我转了几个人,直到我找到了一位知道他在说什么的工程师。事实证明,问题不在于 ORM 引擎(Hibernate)不能将整数识别为整数,而是如果你有一个引用另一个持久实体的外键,那么你必须传递 实体 而不是 ID。
示例(在问题的上下文中)
首先,我从问题中删除了 type
和 sqltype
值,因为前者可以通过检查数据库的 CF 检索(在我的情况下这很好,但你可以必须明确设置它,特别是如果您在 Application.cfc).
中关闭了 useDBforMapping
其次,我已将模板组件中的 userID
属性 重命名为 user
,因为它可能会帮助那些不能立即理解我上面所说的关于 'passing the entity' 更好地形象化它。
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
属性,而是创建一个用户组件,然后传递 that.
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
TL:DR;
具有外键约束的 CF ORM 组件的正确 syntax/workaround/hack 是什么?
ColdFusion + 整数
将变量存储为整数应该是一个简单的编程问题,对吧?在该语言的文档中找到适当的函数(如果您不记得它),它会说 returns: int (owtte) 并使用它。
不适用于 ColdFusion。
有些人可能已经知道 ColdFusion 的 various issues with integers,但目前导致我快速脱发的是 ColdFusion 有时会将您的 "integer" 存储为字符串、双精度或长。现在,对于大多数用例来说,这不是一个破坏功能的问题,而且通常是 overlooked/ignored/undiscovered。就我而言,例外情况是 ORM 开始发挥作用时。当然,就像任何明智的开发人员一样,我认识到这可能归结为某处的用户错误。
问题
只要 CF 尝试与 DB 交互,就会出现问题。如果有一个字段是外键并且类型为 'integer',CF 将抛出一个 Hibernate 异常并显示以下消息:
java.lang.Integer
就是这样。有帮助,对吧?我发现这个 "error message" 明确是您传递给该字段的变量类型,因此如果您错误地将双精度传递给该字段,错误消息将显示为 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";
}
刷新已更新的 ORM 时出现问题 template.userID
。
我尝试过的事情
- 联系 Adobe CF 支持(我们有白金支持的企业许可证,但在一个月内他们无法给我一个解决方案甚至 "it's not working?" 以外的任何信息)
- 将
ormtype
属性添加到标识字段(然后在不起作用时添加外键字段) - 更改
sqltype
属性(我现在相信 is only for table creation 因为数据库已经就位,我们从来不需要它) - 使用以下函数的各种组合转换变量:
NumberFormat( var )
- 文档说 returns 'A formatted number value',实际上 returns 一个java.lang.String
LSParseNumber( var )
- returns一个双Int( var )
- 这个很棒:文档说它 returns 一个 整数 ,作为一个 字符串 。实际上returns一个java.lang.Double
Val( var )
- returns 双javaCast( 'int', var )
- returns 一个整数,抛出相同的错误
- 在 属性 上设置
elementtype
属性(两端) - 放宽属性(两端)上的
validate
属性为'numeric'
我怀疑这可能与 Hibernate 和 CF 的组合有关,而不仅仅是 CF,尽管它是 javascript- 令人怀念的怪癖,但我仍然喜欢它。
环境
- Windows 服务器 2012 R2
- ColdFusion 2016(企业版)
- SQL 服务器
TL:DR;
传递实体,而不是 ID。 引用持久实体 Foo 的 CF ORM 中的外键 属性 是 Foo 类型而不是 int。
更多详情
经过这么长时间,Adobe 让我转了几个人,直到我找到了一位知道他在说什么的工程师。事实证明,问题不在于 ORM 引擎(Hibernate)不能将整数识别为整数,而是如果你有一个引用另一个持久实体的外键,那么你必须传递 实体 而不是 ID。
示例(在问题的上下文中)
首先,我从问题中删除了 type
和 sqltype
值,因为前者可以通过检查数据库的 CF 检索(在我的情况下这很好,但你可以必须明确设置它,特别是如果您在 Application.cfc).
useDBforMapping
其次,我已将模板组件中的 userID
属性 重命名为 user
,因为它可能会帮助那些不能立即理解我上面所说的关于 'passing the entity' 更好地形象化它。
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
属性,而是创建一个用户组件,然后传递 that.
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