如何使用ColdFusion ORM存储整数?

时间:2017-08-21 15:04:55

标签: java orm coldfusion integer coldfusion-2016

TL:DR;

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

ColdFusion +整数

将变量存储为整数应该是一个简单的编程问题,对吧?在语言文档中找到适当的函数(如果你无法从圆顶上回忆起来),它会说返回: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时会出现问题。

我尝试过的事情

  • 联系Adobe CF支持(我们拥有铂金支持的企业许可证,但在一个月内他们无法向我提供解决方案,甚至除了“它不起作用之外的任何信息?”)
  • 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-回忆的怪癖,我仍然喜欢它。

环境

  • Windows Server 2012 R2
  • ColdFusion 2016(企业)
  • SQL Server

非常感谢任何和所有帮助。

由于

JC

1 个答案:

答案 0 :(得分:0)

TL:DR;

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

更多细节

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

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

首先,我从问题中删除了typesqltype值,因为前者可以通过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