配置 SORM 的最佳实践
Posted
技术标签:
【中文标题】配置 SORM 的最佳实践【英文标题】:Best practices for configuring SORM 【发布时间】:2013-10-07 23:32:25 【问题描述】:我想知道是否有人可以分享一些使用 SORM 的最佳实践,参考在参与者系统中使用和自动化测试(单元/功能)。
你好吗:
从运行时构建的外部化配置(例如 typesafe 的 application.conf)驱动您的 DB/Instance 单例 执行依赖注入(构造函数或蛋糕模式或?)以将相同的代码用于生产/测试 DB .. 还是完全使用其他策略?似乎当我不将我的“实例”声明为单例(对象扩展实例)而是创建一个新实例以注入我的演员进行测试时,我遇到了使用 SORM 的奇怪堆栈跟踪。我使用了 scala 2.10.2/3、SORM 0.38/9,结果相同。这是我的(唯一)实体:
object TapJoy
private val SECRET_KEY = "aaa"
case class AddCreditsRequest(tapJoyId: String, verifier: String, currency: Int, snuid: Long)
val created = new DateTime()
<some methods omitted>
堆栈跟踪:
java.lang.ClassCastException: scala.reflect.internal.Types$TypeRef$$anon$3 cannot be cast to scala.reflect.internal.Symbols$Symbol
at scala.reflect.internal.pickling.UnPickler$Scan.readSymbolRef(UnPickler.scala:788)
at scala.reflect.internal.pickling.UnPickler$Scan.readType(UnPickler.scala:355)
at scala.reflect.internal.pickling.UnPickler$Scan$LazyTypeRef$$anonfun$34.apply(UnPickler.scala:855)
at scala.reflect.internal.pickling.UnPickler$Scan$LazyTypeRef$$anonfun$34.apply(UnPickler.scala:855)
at scala.reflect.internal.pickling.UnPickler$Scan.at(UnPickler.scala:171)
at scala.reflect.internal.pickling.UnPickler$Scan$LazyTypeRef.complete(UnPickler.scala:855)
at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1229)
at scala.reflect.internal.Types$TypeRef.thisInfo(Types.scala:2399)
at scala.reflect.internal.Types$TypeRef.baseClasses(Types.scala:2404)
at scala.reflect.internal.Types$Type.findMembers(Types.scala:1093)
at scala.reflect.internal.Types$Type.membersBasedOnFlags(Types.scala:718)
at scala.reflect.internal.Types$Type.members(Types.scala:661)
at scala.reflect.internal.Types$Type.members(Types.scala:343)
at sorm.reflection.ScalaApi$TypeApi.members(ScalaApi.scala:11)
at sorm.reflection.ScalaApi$TypeApi.properties(ScalaApi.scala:13)
at sorm.reflection.Reflection.properties(Reflection.scala:31)
at sorm.core.Initialization$.errors(Initialization.scala:29)
at sorm.Instance$Initialization$$anonfun$2.apply(Instance.scala:212)
at sorm.Instance$Initialization$$anonfun$2.apply(Instance.scala:212)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.immutable.Set$Set1.foreach(Set.scala:74)
at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:251)
at scala.collection.AbstractTraversable.flatMap(Traversable.scala:105)
at sorm.Instance$Initialization.<init>(Instance.scala:212)
at sorm.Instance.<init>(Instance.scala:29)
或
scala.reflect.internal.Symbols$CyclicReference: illegal cyclic reference involving method productPrefix
at scala.reflect.internal.Symbols$Symbol$$anonfun$info$3.apply(Symbols.scala:1218)
at scala.reflect.internal.Symbols$Symbol$$anonfun$info$3.apply(Symbols.scala:1216)
at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.reflect.internal.Symbols$Symbol.lock(Symbols.scala:482)
at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1216)
at scala.reflect.internal.Symbols$Symbol.tpe(Symbols.scala:1200)
at scala.reflect.internal.Symbols$Symbol.tpeHK(Symbols.scala:1201)
at scala.reflect.internal.Types$Type.computeMemberType(Types.scala:784)
at scala.reflect.internal.Symbols$MethodSymbol.typeAsMemberOf(Symbols.scala:2646)
at scala.reflect.internal.Types$Type.memberType(Types.scala:779)
at scala.reflect.internal.Types$Type.findMembers(Types.scala:1117)
at scala.reflect.internal.Types$Type.membersBasedOnFlags(Types.scala:718)
at scala.reflect.internal.Types$Type.members(Types.scala:661)
at scala.reflect.internal.Types$Type.members(Types.scala:343)
at sorm.reflection.ScalaApi$TypeApi.members(ScalaApi.scala:11)
at sorm.reflection.ScalaApi$TypeApi.properties(ScalaApi.scala:13)
at sorm.reflection.Reflection.properties(Reflection.scala:31)
at sorm.core.Initialization$.errors(Initialization.scala:29)
at sorm.Instance$Initialization$$anonfun$2.apply(Instance.scala:212)
at sorm.Instance$Initialization$$anonfun$2.apply(Instance.scala:212)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.immutable.Set$Set1.foreach(Set.scala:74)
at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:251)
at scala.collection.AbstractTraversable.flatMap(Traversable.scala:105)
at sorm.Instance$Initialization.<init>(Instance.scala:212)
at sorm.Instance.<init>(Instance.scala:29)
【问题讨论】:
绝对没有义务让 SORM 的实例成为单例。似乎问题出在您的代码中。请提供一个信息更丰富的示例,其中至少包括实例的声明。 好的。我会试着想出一个人为的例子。对我的其他问题的任何意见将不胜感激.. 并且会很好地添加到文档中? 【参考方案1】:您如何从运行时构建的外部化配置(例如 typesafe 的 application.conf)驱动您的 DB/Instance 单例?
相当直接。例如:
val db =
val config = readAndParseConfigDataSomehow()
new sorm.Instance(
entities = ...,
url = config.url,
user = config.url,
password = config.url,
poolSize = config.poolSize,
initMode = config.initMode
)
您如何进行依赖注入(构造函数或蛋糕模式或?)以将相同的代码用于生产/测试数据库......还是完全使用另一种策略?
SORM 确实没有任何特殊要求。您可以传递适合您的实例,就像任何其他值一样,因此使用的实际实例可以依赖于上下文:函数或构造函数参数,例如def doSomeStuffWithDB( db : sorm.Instance ) ...
,如果你是它们的粉丝,甚至是隐式参数(我知道我不是)。策略的选择完全取决于您。
关于在生产环境和测试环境之间切换 - 您已经提出了一个明显的解决方案 - 配置文件。
【讨论】:
感谢您的意见。我使用 Spray、Akka 和 SORM 组合了一个简单的(但希望不是人为的)示例应用程序。它目前显示了我的第一篇文章中的问题:github.com/nefilim/sas 我很想知道您是否可以复制它们,只需使用 sbt 运行测试即可。 ps。请注意,我对 Scala 还是很陌生 ;) 对不起,我没有时间分析这个项目。乍一看,它看起来非常复杂,有各种各样的图案,没有任何真正的用途。不过,我可以给你一个解决问题的建议:首先摆脱冗余层like this,然后通过逐步将代码简化为我的答案中提供的简单解决方案来隔离问题。 如果我进行以下两项调整,我可以可靠地使两个链接项目测试成功完成:1. 将 scalaVersion 设置为 2.10.3 和 2. 测试中的 parallelExecution := 错误阅读上述 scala 问题是'不是很令人鼓舞:反射 API 是实验性的,运行时反射应该被序列化等 好像Instance创建的同步解决了这个问题:lazy val connection = TestDatabaseCreationLock.synchronized new TestDB object TestDatabaseCreationLock class TestDB extends Instance( ... )以上是关于配置 SORM 的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章