【问题标题】:Invoking a Hibernate REST @POST method from Dropwizard application run() does not work, but method works when invoked normally from frontend从 Dropwizard 应用程序 run() 调用 Hibernate REST @POST 方法不起作用,但从前端正常调用时方法有效
【发布时间】:2022-01-03 12:58:45
【问题描述】:

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

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

我使用 Hibernate 作为我的 ORM 将我的 Kotlin 对象映射到数据库。我尝试在资源类中使用@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 以测试创建是否有效的最佳方法(但我相信我现在可以从 cmd 行卷曲)。为了测试创建,我只是从我的 Dropwizard 主应用程序类的 .run() 方法中调用了方法 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 会话并创建了对象,但是当我直接从我的后端代码调用该方法时,它不是?感谢你们在这里提供的任何见解,我只是想学习:)

【问题讨论】:

    标签: java hibernate kotlin jpa dropwizard


    【解决方案1】:

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

    像 Spring 和 JAX-RS 这样的框架的工作方式是,在启动时,实际处理 http 请求的代码的引用不是对您的类,而是对动态生成的子类(这就是 cglib 的用途)——如果你在您的方法中打断点,您将看到该对象不是您的类的实例,而是具有生成名称的东西。

    子类覆盖您的方法以使用其他代码来装饰它 - 在本例中是创建 Session。这个包装器代码通常定义在具有基于注释的连接点的方面中,并且 cglib 将该方面代码拉入已编译的子类中。 (如果带注释的方法在接口上,则使用 Java 动态代理而不是 cglib,它只实现接口而不是扩展类)。

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

    【讨论】:

    • 非常感谢您的解释:)
    • 希望它有所帮助,如果有人问一个我知道答案的问题,我会很高兴! (ps,如果您包含带有-d 的数据,则使用 curl 我认为您不需要-X POST,因为这似乎是发送数据时的默认方法
    猜你喜欢
    • 1970-01-01
    • 2014-01-14
    • 2015-07-18
    • 1970-01-01
    • 1970-01-01
    • 2013-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多