Issue
I am creating a web application in Java and would like to use the Javalin framework.
Issues/questions:
- What would be the best way to use href="https://docs.jboss.org/hibernate/orm/5.6/userguide/html_single/Hibernate_User_Guide.html#bootstrap-jpa" rel="nofollow noreferrer">JPA (via hibernate) in a Javalin web application?
- I.e. what is the best way make a JPA
EntityManager
object available to the Javalin request handlers?
Update: Some more context
I want to use JPA (via Hibernate) in my javalin application. The central concept in JPA is that you use an EntityManager
instance to access the database. To create an EntityManager
, there is a EntityManagerFactory
.
What I currently do is that I create a global EntityManagerFactory
and the handlers that use the database call factory.createEntityManager()
.
While this works, I wonder if there are other recommended apporaches? Coming from a Flask/SQLAlchemy/Python background - on that stack the ORM session (EntityManager equivalent) is typically available as a request-bound object.
Solution
I ended up implementing the following:
- Create an
EntityManagerFactory
on startup. Create aJavalin
instance on startup. Then callenableRequestBoundEntityManager(javalinApp, entityManagerFactory)
. - Whenever a handler needs an
EntityManager
, use the extension propertyContext.entityManager
.
I.e.:
fun main() {
val app = Javalin.create()
val emf = createEntityManagerFactorySomehow()
enableRequestBoundEntityManager(app, emf)
app.get("/list/") { ctx -> ctx.json(
ctx.entityManager.createQuery("select ... from ...").resultList
) }
app.start()
}
/**
* Adds an `entityManagerFactory` application attribute, and sets up clean up after requests have been handled
*/
fun enableRequestBoundEntityManager(app: Javalin, entityManagerFactory: EntityManagerFactory) {
app.attribute("entityManagerFactory", entityManagerFactory)
app.after {
val entityManager: EntityManager? = it.attribute("entityManager")
if (entityManager != null) {
entityManager.close()
}
}
}
/**
* Returns a JPA entity manager scoped to the Javalin context
*/
val Context.entityManager: EntityManager
get() {
if (this.attribute<EntityManager>("entityManager") == null) {
this.attribute("entityManager", this.appAttribute<EntityManagerFactory>("entityManagerFactory").createEntityManager())
}
return this.attribute("entityManager")!!
}
Answered By - codeape
Answer Checked By - Timothy Miller (JavaFixing Admin)