从 Dropwizard 应用程序 运行() 调用 Hibernate REST @POST 方法不起作用,但从前端正常调用时方法有效

Invoking a Hibernate REST @POST method from Dropwizard application run() does not work, but method works when invoked normally from frontend

我正在编写我的第一个网络应用程序作为练习学习不同的框架。由于我是新手,如果我犯了任何非常明显的错误,请原谅我。

我正在使用 Dropwizard 和 Kotlin 编写我的应用程序的后端。我正在 运行ning 2 docker 个容器:一个带有 application.jar 文件,另一个带有 PostgreSQL 数据库。当我逐步学习流程和各个框架时,我正在编写某些代码片段以帮助我了解实际发生的事情。

我使用 Hibernate 作为我的 ORM 来将我的 Kotlin 对象映射到数据库。我尝试在我的资源 class 中使用 @POST 方法创建一个随机对象,如下所示。

@POST
@UnitOfWork
fun createNote(@Valid noteRequest : Note){
    println("adding new note")
    val note = createNoteToSave(noteRequest)
    notesDAO.save(note)
}

private fun createNoteToSave(noteRequest: Note) : Note{
    val note = Note()
    note.data = noteRequest.data
    note.type = noteRequest.type
    return note
}

我还没有创建前端,所以我不确定访问此方法的 URL 以测试创建是否有效的最佳方式(但我相信我可以 curl 现在从 cmd 行)。为了测试创建,我只是从我的 Dropwizard 主应用程序 class 的 .运行() 方法中调用了方法 notesResource.createNote(note) 并且我得到了以下错误:

org.hibernate.HibernateException: No session currently bound to execution context

at org.hibernate.context.internal.ManagedSessionContext.currentSession(ManagedSessionContext.java:58)

at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:508)

at io.dropwizard.hibernate.AbstractDAO.currentSession(AbstractDAO.java:44)

at com.ac.notetaker.dao.HibernateDAO.save(HibernateDAO.kt:34)

at com.ac.notetaker.resources.NotesResource.createNote(NotesResource.kt:34)

at com.ac.notetaker.NotetakerApplication.run(NotetakerApplication.kt:95)

at com.ac.notetaker.NotetakerApplication.run(NotetakerApplication.kt:22)

它表示 Hibernate 会话尚未启动,但 @UnitOfWork 注释不应该表示无论何时调用该方法,会话都应该开始吗?

相反,因为我没有前端,所以我创建了一个@GET 方法,然后依次调用@POST 方法,如下所示。当我访问这个URL时,@POST方法被连续调用并创建一个对象并添加到数据库中。

@GET
@Path("add")
@UnitOfWork
fun addRandomNote(){
    this.createNote(Note(
        UUID.randomUUID(),
        "{\"question\":\"answer\"}",
        Note.Type.QuestionAndAnswer.toString(),
    ))
}

为什么,当我使用 @GET url 访问该方法时,该方法是否成功创建了 Hibernate 会话并创建了对象,但是当我直接从我的后端代码调用该方法时,它不是'吨?感谢你们在这里提供的任何见解,我只是想学习 :)

这是有道理的 - 如果您直接调用您的方法,那么您只是在执行您的方法代码 - 注释不会导致任何额外的行为。

Spring 和 JAX-RS 等框架的工作方式是,在启动时,实际处理 HTTP 请求的代码所引用的不是您的 class,而是动态生成的subclass(这就是 cglib 的用途)- 如果您在方法中遇到断点,您将看到该对象不是 class 的实例,而是具有生成名称的对象。

subclass 覆盖您的方法以使用附加代码对其进行装饰 - 在本例中为创建会话。此包装器代码通常在带有基于注释的连接点的方面中定义,cglib 将该方面代码拉入已编译的 subclass。 (如果带注释的方法在接口上,则使用 Java 动态代理而不是 cglib,它只实现接口而不必扩展 class)。

您确实可以从 curl 中调用您的 post - 试试 curl -X POST localhost:8080/the_path -H 'Content-type:application/json' -d '{"question":"answer"}'