使用 CF-ORM 的 ColdFusion 9 需要注意的事项
您在带有 CF-ORM (Hibernate) 的 ColdFusion 9 中观察到了哪些应该注意的事情?
What are some of the things you've observed in ColdFusion 9 with CF-ORM (Hibernate) that one should watch out for?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
entity
init()
方法不得包含必需的参数,否则EntityNew()
和其他 CF-ORM 操作将中断。您可能想要使用工厂来创建实体,并在其中强制执行所需的参数。有关此限制的错误已在 Adobe Bugbase 中提交。< /a>
ORMReload()
与ormsettings.dbcreate = "drop create"
可能不会为您删除所有表。 CF9 Cumulative Hot Fix 1 稍微改进了这一点,但您可能想要放弃自己在数据库中的表。type="date"
(默认使用ormtype="date"
),仅存储日期而不存储时间。如果您还想保留时间,请使用ormtype="timestamp"
type="string"
将默认为varchar(255)
type="numeric"
默认为 <代码>浮点,而不是<代码>整数。如果需要,请使用 ormtype="int"。如果
fieldtype="id"
并且生成器设置为某个生成器,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)< /code> vs
addDogs(Dog dogs)
.)
将加载所有延迟加载属性。或者,您可以尝试
或设置 top=1 以高效转储。存储在Session作用域中的实体将与其Hibernate会话作用域断开连接,并且不会加载延迟加载属性。要恢复 Hibernate 会话范围,请使用
entityLoadByExample()
或entitySave(entity)
。cascade="all-delete-orphan"
通常对于“一对多”或“多对多”关系更有意义。 Hibernate 设置 null 然后删除,因此请确保该列可以为 null。测试一下,看看这是否是您想要的行为。每当
notnull="true"
时设置required="true"
,对于使用 CFCExplorer 浏览 CFC 的其他人来说更具可读性EntityNew('Y')
效率比new com.XY
如果根据某些 Adobe 工程师的说法,实体稍后要保留。由于未修复的 Hibernate bug,与继承实体的关系有时可能会中断,请使用
linktable
作为解决方法。由于未修复的
structKeyColumn
不能是目标实体的 PK。双向多对多不能使用struct
向struct添加新实体时,
structKeyColumn
会被忽略CF 保留父实体。如果直接访问一对多/多对多数组或结构体,请在使用前确保相应的数组/结构体存在。生成的 addX()/hasX()/removeX() 可以随时安全使用。
在
postInsert()
处,实体休眠会话不再可用,因此在 postInsert() 处设置属性将被静默忽略,或者将抛出 Session is Closed 异常。通过
entityLoad()
或HQL从数据库加载实体后,即使不调用EntitySave()
,更改也会自动保留。CF-ORM 事务的实现方式
在事件(即 preLoad() / postInsert())内,分配给变量可能会引发有关类型的 Java 异常。使用 JavaCast() 来解决该错误。
更新
,更容易做到cfqueryparam
,并且调试输出实际上向您显示绑定值。entity
init()
method must not have required argument(s), otherwiseEntityNew()
and other CF-ORM actions will break. You may want to use a Factory to create the entity, and enforce the required arguments there.A bug regarding this limitation has been filed in the Adobe Bugbase.
ORMReload()
withormsettings.dbcreate = "drop create"
might not drop all tables for you. CF9 Cumulative Hot Fix 1 improves this a little bit, but you might want to drop the tables in DB yourself.type="date"
(default to useormtype="date"
), will only store date but not time. If you want to persisted time as well, useormtype="timestamp"
type="string"
will default tovarchar(255)
type="numeric"
will default tofloat
, notint
. Use ormtype="int" if needed.if
fieldtype="id"
and generator is set to some generator, ormtype will default toint
.type="string" length="10"
will usevarchar(10)
, notchar(10)
ormtype="char" length="10"
will usechar(1)
still. Usesqltype="char(10)"
if you really need to.type="boolean"
usetinyint
by default, usesqltype="bit"
if you need to.should use
inverse=true
in a bi-directional relationship, usually in "one-to-many" side.do NOT use
inverse="true"
in uni-directional relationship! The relationship might not be persisted at all!If you use MS-SQL, you cannot have more than 1 entity with one-to-one property set to Null, because Null is considered as an unique value in an index. Good idea to make column not null. (or use linktable)
EntityLoad("entity", 1, true)
works, butEntityLoadByPK("entity", 1)
is cleaner!EntityLoad()
,EntityLoadByPK()
, andORMExecuteQuery
withunique=true
, will returnnull
if entity is not found. UseisNull()
to check before you use the returned value.ORMExecuteQuery
will return empty array if no entity is found by default.don't forget to use
singularname
property in "one-to-many" / "many-to-many" for nicer looking generated functions (e.g.addDog(Dog dog)
vsaddDogs(Dog dogs)
.)<cfdump>
will load all the lazy-load properties. Alternatively you may try<cfdump var="#entityToQuery([entity])#">
or set top=1 to dump efficiently.entity stored in Session scope will be disconnected with its Hibernate session scope, and lazy load property will not be loaded. To restore the hibernate session scope, use
entityLoadByExample()
orentitySave(entity)
.cascade="all-delete-orphan"
usually make more sense for "one-to-many" or "many-to-many" relationship. Hibernate sets null then delete, so make sure the column is nullable. Test and see if that's your desire behaviour.set
required="true"
whenevernotnull="true"
, more readable for others browsing the CFC with CFCExplorerEntityNew('Y')
is slightly more efficient thannew com.X.Y
if the entity is to be persisted later according to some Adobe engineer.relationship with an inherited entity may break sometimes due to an unfixed Hibernate bug, use
linktable
as a workaround.structKeyColumn
cannot be the PK of the target entity.bi-directional many-to-many cannot use struct
When adding new entity to struct,
structKeyColumn
is ignored when CF persists the parent entity.If you access the one-to-many / many-to-many array or struct directly, make sure the corresponding array/struct exists before use. Generated addX()/hasX()/removeX() are safe to use anytime.
at
postInsert()
, the entity hibernate session is no longer available, so setting property at postInsert() will be silently ignore, or Session is Closed exception will be thrown.after entity is loaded by
entityLoad()
or HQL from DB, the changes will be automatically persisted even ifEntitySave()
is not called.transaction with CF-ORM is implemented in a way that it starts a new session and close when it's done.
inside the event (i.e. preLoad() / postInsert()), assigning to variables might throw Java exception about types. Use JavaCast() to work around the bug.
UPDATE
<cfquery dbtype="hql">
, easier to docfqueryparam
, and debug output actually shows you the binded values.添加建议:
Add'l recommendations:
结合处理 Hibernate 日志记录,您还可以关闭数据源的“维护连接”。
使用 SQL Server 2005,您可以启动探查器并观察正在进行的查询。
由于维护连接已关闭,Hibernate 将被迫每次创建新的准备好的语句。
阅读准备好的语句可能很困难,但至少您可以看到正在生成的原始查询。
如果您维护连接,这些准备好的语句将创建一次,您只会看到类似
sp_execute 15, 'someparam' 的
内容,在此之前运行 sp_prepexec 是 15 的来源。
In conjunction with fiddling with the Hibernate logging you can also turn "maintain connections" off for your datasource.
With SQL Server 2005 you can then launch profiler and watch the queries coming thru.
Since maintain connections is off Hibernate will be forced to create new prepared statements each time.
Reading prepared statements can be tough, but at least you can see the raw queries that are being generated.
If you maintain connections these prepared statements are created once and you just see something like
sp_execute 15, 'someparam'
Before this was ran sp_prepexec was ran which is where the 15 comes from.
EntityReload 似乎会忽略 CFDUMP 等延迟加载。
我在 EntitySave 之后使用它来获取数据库中的任何默认列。我在 SQL Profiler(SQL Server 的跟踪工具)中看到大量查询。
如果将其更改为 EntityLoadByPK 等,它将加载对象,并且不会看到所有多余的关系查询,这对我来说可能会导致重大问题。
EntityReload appears to ignore lazy loading like CFDUMP.
I use it after an EntitySave to grab any defaulted columns in the db. I see in SQL Profiler ( a tracing tool for SQL Server ) lots of queries coming thru.
If change it to a EntityLoadByPK, etc it will load up the object and will not see all the excess relationship queries which for me can cause major problems.