【问题标题】:JPA query in Play for Scala throws compilation errorPlay for Scala 中的 JPA 查询引发编译错误
【发布时间】:2018-02-16 21:21:35
【问题描述】:

我正在尝试在 Play for Scala 中实现 JPA 查询。我从here 获取信息,但由于示例是用Java 编写的,我可能弄错了。这是代码:

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
      })
   }
}

编译时出现以下错误:

withTransaction 的重载方法值与备选方案:[T](x$1: 字符串,x$2:布尔值,x$3:java.util.function.Supplier[T])T (x$1: Runnable)Unit [T](x$1: java.util.function.Supplier[T])T [T](x$1: 字符串, x$2: 布尔值, x$3: java.util.function.Function[javax.persistence.EntityManager,T])T [T](x$1: 字符串, x$2: java.util.function.Function[javax.persistence.EntityManager,T])T [T](x$1: java.util.function.Function[javax.persistence.EntityManager,T])T 不能应用于 (javax.persistence.EntityManager ⇒ 列表[admin.manage.BankHib])

这段代码有什么问题?如何使查询工作?

【问题讨论】:

  • 如果将 (em: EntityManager) => 替换为 em -> only
  • 这并不能解决问题,因为 Scala 中的 -&gt; 用于 Map 结构

标签: scala playframework playframework-2.0 playframework-2.5


【解决方案1】:

这是因为play.db.jpa.JPAApi.withTransaction 具有以下签名:

  1. withTransaction(java.util.function.Function&lt;javax.persistence.EntityManager,T&gt;)
  2. withTransaction(java.lang.String, java.util.function.Function&lt;javax.persistence.EntityManager,T&gt;)
  3. withTransaction(java.lang.String, boolean, java.util.function.Function&lt;javax.persistence.EntityManager,T&gt;)
  4. withTransaction(java.util.function.Supplier&lt;T&gt;)
  5. withTransaction(java.lang.Runnable)
  6. 最后是withTransaction(java.lang.String, boolean, java.util.function.Supplier&lt;T&gt;)

但是您传递的是 (javax.persistence.EntityManager ⇒ List[admin.manage.BankHib]) 类型的 Scala 函数。因此,错误的类型和编译器抱怨说它无法找到替代方案。

那么正确的方法是使用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
      }
    })
  }
}

另外,请注意,您不需要混合使用 JPAApiJPA 来获得 EntityManager,因为 JPAApi 具有已将其提供给给定函数的方法。

【讨论】:

  • 所以不需要关闭EntityManager?
  • @ps0604 无需关闭它。 Play 为您处理。
  • 我假设我不需要启动/提交事务,因为 @Transactional 隐含地涵盖了这一点
  • 是的,您可以在此处删除@Transactional
【解决方案2】:

看看这是否有效

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
      })
   }
}

【讨论】:

    猜你喜欢
    • 2023-03-14
    • 1970-01-01
    • 2017-04-08
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多