您在使用 CF-ORM (Hibernate) 的 ColdFusion 9 中观察到的哪些事情需要注意?
4 回答
实体
init()
方法不能有必需的参数,否则EntityNew()
其他 CF-ORM 操作将中断。您可能希望使用工厂来创建实体,并在那里强制执行所需的参数。ORMReload()
withormsettings.dbcreate = "drop create"
可能不会为您删除所有表格。 CF9 Cumulative Hot Fix 1稍微改进了这一点,但您可能希望自己删除 DB 中的表。type="date"
(默认使用ormtype="date"
),将只存储日期而不存储时间。如果您还想保持时间,请使用ormtype="timestamp"
type="string"
将默认为varchar(255)
type="numeric"
将默认为float
,而不是int
。如果需要,请使用 ormtype="int"。如果
fieldtype="id"
和 generator 设置为某个生成器,ormtype 将默认为int
.type="string" length="10"
会用varchar(10)
,不会char(10)
ormtype="char" length="10"
仍将使用char(1)
。sqltype="char(10)"
如果您确实需要,请使用。type="boolean"
tinyint
默认使用,sqltype="bit"
需要时使用。应该
inverse=true
在双向关系中使用,通常在“一对多”方面。不要在单向关系中使用
inverse="true"
!这段关系可能根本就不会维持下去!如果您使用 MS-SQL,则不能有超过 1 个将一对一属性设置为 Null 的实体,因为 Null 被视为索引中的唯一值。使列不为空的好主意。(或使用链接表)
EntityLoad("entity", 1, true)
工作,但EntityLoadByPK("entity", 1)
更清洁!EntityLoad()
,EntityLoadByPK()
, 和ORMExecuteQuery
,如果找不到实体unique=true
,将返回。null
用于在使用isNull()
返回值之前进行检查。ORMExecuteQuery
如果默认没有找到实体,将返回空数组。不要忘记
singularname
在“一对多”/“多对多”中使用属性以获得更好看的生成函数(例如addDog(Dog dog)
vsaddDogs(Dog dogs)
.)<cfdump>
将加载所有延迟加载属性。或者,您可以尝试<cfdump var="#entityToQuery([entity])#">
或设置 top=1 以有效转储。存储在 Session 范围内的实体将与其 Hibernate 会话范围断开连接,并且不会加载延迟加载属性。要恢复休眠会话范围,请使用
entityLoadByExample()
或entitySave(entity)
。cascade="all-delete-orphan"
通常对“一对多”或“多对多”关系更有意义。Hibernate 设置 null 然后删除,因此请确保该列可以为空。测试并查看这是否是您的愿望行为。required="true"
随时设置notnull="true"
,对于使用 CFCExplorer 浏览 CFC 的其他人来说更具可读性EntityNew('Y')
new com.X.Y
根据某些 Adobe 工程师的说法,如果实体稍后被持久化,它的效率会稍高一些。由于未修复的 Hibernate 错误,与继承实体的关系有时可能会中断,
linktable
用作解决方法。structKeyColumn
不能是目标实体的PK。双向多对多不能使用struct
将新实体添加到结构时,
structKeyColumn
当 CF 保留父实体时将被忽略。如果直接访问一对多/多对多数组或结构体,使用前请确保对应的数组/结构体存在。生成的 addX()/hasX()/removeX() 可以随时安全使用。
在
postInsert()
,实体休眠会话不再可用,因此在 postInsert() 设置属性将被静默忽略,否则将抛出 Session is Closed 异常。在实体被
entityLoad()
DB 或 HQL 加载后,即使EntitySave()
没有调用,更改也会自动持久化。CF-ORM 的事务以启动新会话并在完成后关闭的方式实现。
在事件内部(即 preLoad() / postInsert()),分配给变量可能会引发关于类型的 Java 异常。使用 JavaCast() 来解决该错误。
更新
- CF9.0.1+:使用
<cfquery dbtype="hql">
,更容易做cfqueryparam
,调试输出实际上显示了绑定的值。
添加建议:
- 关闭 ormsettings.flushAtRequestEnd = false 以在请求结束时不自动刷新。而是在所有写入事务(entitySave() 或编辑持久化实体时)使用事务(从 CF9.01 开始,cftransaction 刷新会话以完成事务)。
- 通过在 HQL 中使用绑定参数来防止 SQL 注入 - 未命名的“?” 或命名为 ':' 符号,以确保 ORM 对相关字段的类型绑定(就像 CFQUERYPARAM 一样)。防止SQL注入!
- CF9.0.1 允许 CFQUERY dbtype="hql" 内联写入和输出 HQL。使用 CFQUERYPARAM 绑定内联参数(相当于 HQL 中的未命名 ? 表示法)。
- 在 HQL 中使用 LEFT OUTER JOIN FETCH 来急切获取关系。
- 覆盖具有双向关系的 CFC 上的添加/删除功能,以确保双方都已设置。
- 打开 ormsettings.logsql=true 在控制台中查看派生的 SQL。调整 log4j Hibernate 设置以进一步调整来自 Hibernate 的日志设置。
- 加入 Google 群组 cf-orm-dev。那里的人很聪明。
结合使用 Hibernate 日志记录,您还可以为您的数据源关闭“维护连接”。
使用 SQL Server 2005,您可以启动探查器并观察通过的查询。
由于保持连接关闭,Hibernate 将被迫每次创建新的准备好的语句。
阅读准备好的语句可能很困难,但至少您可以看到正在生成的原始查询。
如果您保持连接,这些准备好的语句会创建一次,您只会看到类似
sp_execute 15, 'someparam'
在此之前运行 sp_prepexec 是 15 的来源。
EntityReload 似乎忽略了像 CFDUMP 这样的延迟加载。
我在 EntitySave 之后使用它来获取数据库中的任何默认列。我在 SQL Profiler(SQL Server 的跟踪工具)中看到了很多查询。
如果将其更改为 EntityLoadByPK 等,它将加载对象并且不会看到所有多余的关系查询,这对我来说可能会导致重大问题。