ColdFusion中的多个Hibernate会话?
我正在从事一个项目,该项目要求我们能够修改ORM实体上的数据,但不能将数据持久化回数据库。本质上,我们需要修改对象并将其传递给对数据执行某些计算的服务,然后在结束请求时不实际保留任何数据。问题是执行计算的服务不需要保存一些数据(运行日志、计算结果)。这意味着,一旦流程完成,我们不能只清除整个会话 我们正在处理的实体相对复杂(至少有十几个关系和许多更简单的属性),因此在刷新之前从会话中逐出实体及其所有相关实体并不是最佳选择。为了让事情变得更加困难,在执行计算的服务中有一些ColdFusion中的多个Hibernate会话?,hibernate,coldfusion,coldfusion-10,Hibernate,Coldfusion,Coldfusion 10,我正在从事一个项目,该项目要求我们能够修改ORM实体上的数据,但不能将数据持久化回数据库。本质上,我们需要修改对象并将其传递给对数据执行某些计算的服务,然后在结束请求时不实际保留任何数据。问题是执行计算的服务不需要保存一些数据(运行日志、计算结果)。这意味着,一旦流程完成,我们不能只清除整个会话 我们正在处理的实体相对复杂(至少有十几个关系和许多更简单的属性),因此在刷新之前从会话中逐出实体及其所有相关实体并不是最佳选择。为了让事情变得更加困难,在执行计算的服务中有一些或mflush()调用,这
或mflush()
调用,这使得手动逐出实体几乎不可能。由于有大量的关系,在我们将其发送到服务之前,急切地加载所有内容然后将其全部删除是不可行的
由于这些问题,我试图打开第二个Hibernate会话(基本上是一个沙盒),它永远不会被刷新。我们可以加载实体并在该会话中进行所需的任何更改,而不必担心持久化到数据库的更改
到目前为止,它已经成功了,但有一个例外:我无法对实体调用隐式的“has”方法(例如,hasFoo()
,hasBar()
),这会导致NullPointerException
示例代码:
ormSession = ormGetSessionFactory().openSession();
person = ormSession.load( "person", javaCast( "int", 123 ) );
// assume person has a o2m relationship for "brother"
writeOutput( person.hasBrother() );
这将导致以下异常:
java.lang.NullPointerException at
coldfusion.orm.ImplicitRelationUDF.runHasMethodWithNoArgs(ImplicitRelationUDF.java:410) at
coldfusion.orm.ImplicitRelationUDF.invoke(ImplicitRelationUDF.java:246) at
coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:431) at
coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:414) at
coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2432) at
cfsean2ecfm1294924799.runPage(C:\websites\test.cfm:11)
我的直觉是ImplicitRelationUDF.java正在尝试使用“标准”CF Hibernate会话,并且失败了,因为该实体加载在不同的会话中,但我不知道在这一点上如何进一步研究
我采取了另一种仍然不起作用的方法,但(也许)值得思考。它抛出与上面代码相同的错误
transaction {
person = entityLoadByPK( "person", 123 );
transaction action="rollback";
}
writeOutput( person.hasBrother() );
我愿意解决特定问题(修复has*)或更一般的问题,即修改实体并确保数据不会持久化回数据库。我知道您使用的实体相对复杂,但我现在能想到的就是在其中编写一个克隆方法,将它拥有的所有内容克隆到一个新实例中,该实例不连接到任何会话,并使用该方法将克隆的实例传递给需要orm持久化的服务 也许有更好的解决办法,但如果时间有限,我很肯定这会奏效
我很乐意学习如何使用ORM会话处理此问题,因为我已经了解到它在ColdFusion中没有很好地实现。将会话默认设置为只读
ormSession = ormGetSessionFactory().openSession();
ormSession.setDefaultReadOnly( true );
person = ormSession.load( "person", javaCast( "int", 123 ) );
会话中调用的任何内容都将是只读的您可以尝试在Application.cfc中设置
flushatrequestend=false
。这意味着提交ORM更改的唯一方法是在调用entitySave()
后手动调用ORMFlush()
。在需要持久化数据的服务中,在对这些对象调用完entitySave()
后,您只需调用或mflush()
。@ScottStroz在刷新ORM时-手动或通过flushatrequestend
自动-它将持久化任何持久化数据(例如,通过new/entityNew加载而不是创建)不管entitySave()
calls.Crap()如何,都具有脏属性的实体……忘了这一点。愚蠢的Hibernate。如果你将逻辑完全解耦成可以在单独线程中运行的东西怎么办?@BradWood我不确定我是否在跟踪-请你详细说明一下好吗?这是一个可能的解决方案,但我真的希望避免预先加载所有内容,如果要克隆实体,我们需要这样做。如果您有延迟加载,那么您可以将所需内容浅拷贝到服务层的新实例中,而不是编写克隆方法并克隆所有内容。这是可行的,但相当愚蠢。希望一些hibernate会话专家能给你一个更好的解决方案。Sam,实体将是只读的,但我们仍然无法访问隐式has*方法。
ormSession = ormGetSessionFactory().openSession();
ormSession.setDefaultReadOnly( true );
person = ormSession.load( "person", javaCast( "int", 123 ) );