【发布时间】:2020-11-25 19:40:00
【问题描述】:
我目前正在使用 Kotlin/ktor 和 Hibernate(没有 Spring!)开发一个服务器应用程序,我对处理 Hibernate 会话和事务的方式不太满意。所以我正在寻找一些关于如何改进我的设置的建议,或者(如果有理由的话)一些保证,我正在做的事情实际上并没有那么糟糕。
所做的任何调用都将被转发到处理函数,该处理函数在 ktors 路由功能中调用。
route("foo"){
get {
FooHandler.doStuff(call)
}
//...
}
省略处理请求和响应,这些函数(例如doStuff())可能如下所示:
suspend fun doStuff(call: ApplicationCall) {
val session = HibernateDBA.sessionFactory.openSession()
session.beginTransaction()
SomeDAO(session).makeChanges(someObj)
SomeOtherDAO(session).makeChanges(someOtherObj)
session.transaction.commit()
session.close()
}
如您所见,我将会话传递给 DAO 的构造函数,因为 makeChanges() 需要会话(例如,对于 session.persist(someObj))。这里困扰我的是,我必须在每个处理函数中包含相同的 4 行代码。
我还想指出,我有意在示例中包含多个 DAO,因为这在我的应用程序中很常见,这也是我努力寻找令人满意的解决方案的核心原因.如果这很愚蠢,请随时指出,因为我仍在学习专门使用数据库和 Hibernate。在这种情况下,我将非常感谢有关如何避免这种情况的建议。
我最初的想法是拦截每个呼叫以在Routing.RoutingCallStarted 创建我的会话并在Routing.RoutingCallFinished 关闭它。这将删除每个函数中的 2 行,但迫使我以某种方式管理 call 和 session 之间的关系(在地图或其他东西中),这对我来说似乎有点矫枉过正。
另一种方法是在需要的地方链接我的 DAO,并在构造函数调用时打开会话,或者在需要时将现有会话传递给构造函数,如下所示:
class SomeDAO (val session: Session = HibernateDBA.sessionFactory.openSession()) {
fun makeChanges(someObj : SomeClass, someOtherObj : SomeOtherClass) {
session.persist(someObj)
SomeOtherDAO(session).makeChanges(someOtherObj)
}
}
DomeOtherDAO 将具有相同的布局,包括构造函数。
然后我的处理程序只需要调用SomeDAO().makeChanges(someObj, someOtherObj),而不是第二个块中的六行代码。听起来不错,但它没有:
- 现在我将 someOtherObj 传递给 SomeDAO,这显然是不对的
- 我还没有解决事务处理。我没有忘记它,在这个例子中我什至想不出一个伪解决方案。我必须知道事务总是以
SomeDAO.makeChanges()开始并以SomeOtherDAO.makeChanges()结束 - 此外,在阅读该想法时,我发现多个声明让我放心,链接 DAO 通常是不好的做法
这就是我现在卡住的地方。我有一些想法如何不这样做,但我仍然觉得离我想去的地方更近。所以我的结论性问题是:我应该在哪里(也许如何)管理我的会话和事务,以便能够跨多个 DAO 工作?
【问题讨论】:
标签: hibernate kotlin session transactions ktor