ps0604
ps0604

Reputation: 1071

JPA query in Play for Scala throws compilation error

I'm trying to implement a JPA query in Play for Scala. I took the information from here, but since the examples are in Java I'm probably mistaken. This is the code:

class ManageBanks @Inject() (jpaApi: JPAApi) extends Controller {

   @Transactional
   def readMany = {
      val em = jpaApi.em

      jpaApi.withTransaction( (em: EntityManager) => {   //  <-- error in this line
          val query = em.createQuery("from BankHib order by name")
          val list = query.getResultList.asScala.toList.map(_.asInstanceOf[BankHib])
          list
      })
   }
}

I get the following error when I compile:

overloaded method value withTransaction with alternatives: [T](x$1: String, x$2: Boolean, x$3: java.util.function.Supplier[T])T (x$1: Runnable)Unit [T](x$1: java.util.function.Supplier[T])T [T](x$1: String, x$2: Boolean, x$3: java.util.function.Function[javax.persistence.EntityManager,T])T [T](x$1: String, x$2: java.util.function.Function[javax.persistence.EntityManager,T])T [T](x$1: java.util.function.Function[javax.persistence.EntityManager,T])T cannot be applied to (javax.persistence.EntityManager ⇒ List[admin.manage.BankHib])

What's wrong with this code? How to make the query work?

Upvotes: 0

Views: 222

Answers (2)

marcospereira
marcospereira

Reputation: 12214

This is because play.db.jpa.JPAApi.withTransaction has the following signatures:

  1. withTransaction(java.util.function.Function<javax.persistence.EntityManager,T>)
  2. withTransaction(java.lang.String, java.util.function.Function<javax.persistence.EntityManager,T>)
  3. withTransaction(java.lang.String, boolean, java.util.function.Function<javax.persistence.EntityManager,T>)
  4. withTransaction(java.util.function.Supplier<T>)
  5. withTransaction(java.lang.Runnable)
  6. And finally withTransaction(java.lang.String, boolean, java.util.function.Supplier<T>).

But you are instead passing a Scala function of type (javax.persistence.EntityManager ⇒ List[admin.manage.BankHib]). So, wrong type and the compiler complains saying that it was not able to find an alternative.

The correct way then is to use a java.util.function.Function[EntityManager, List]:

class ManageBanks @Inject()(jpaApi: JPAApi) extends Controller {

  def readMany = {
    jpaApi.withTransaction(new java.util.function.Function[EntityManager, List[BankHib]] {
      override def apply(em: EntityManager): List[BankHib] = {
        val query = em.createQuery("from BankHib order by name")
        query.getResultList.asScala.map(_.asInstanceOf[BankHib]).toList
      }
    })
  }
}

Also, notice that you don't need to mix JPAApi and JPA to get an EntityManager since JPAApi has methods that already provides it to the given function.

Upvotes: 1

muasif80
muasif80

Reputation: 6006

See if this works

class ManageBanks @Inject() (jpaApi: JPAApi) extends Controller {

   @Transactional
   def readMany = {


      jpaApi.withTransaction( () => {   //  <-- error in this line
          val em = JPA.em() // or jpaApi.em
          val query = em.createQuery("from BankHib order by name")
          val list = query.getResultList.asScala.toList.map(_.asInstanceOf[BankHib])
          list
      })
   }
}

Upvotes: 0

Related Questions