Kotlin +春季+ JPA +投影+动态SQL语句

问题描述

我已经成功创建了以下与@Query注释结合的投影:

方法1

interface Deployment{
  val app: String
  val platform: String
  val org: String
  val space: String
  val instances: Int
  val state: String
}

@Query(value="select a.name as app,p.name as platform,o.name as org,s.name as space,a.instances as instances,a.state as state " +
    "from apps a " +
    "inner join spaces s on a.space_id = s.id " +
    "inner join orgs o on s.org_id = o.id " +
    "inner join platforms p on o.platform_id = p.id " +
    "where o.name = :eai " +
    "and lower(a.name) = lower(:app) " +
    "and lower(a.state) = lower(:state) " +
    "order by p.name,s.name",nativeQuery = true)
fun getDeploymentsByEaiAndAppAndState(eai: String,app: String?,state: String?): List<Deployment>

方法2

但是,我需要根据过滤器中提供的信息动态创建sql语句:

data class DeploymentFilter(
    val eai: String
    )
{
  var app: String? = null
  var state: String? = null
}

override fun getByFilter(filter: DeploymentFilter): List<Deployment> {
  var sql =
    "select a.name as app,a.state as state " +
    "from apps a " +
    "inner join spaces s on a.space_id = s.id " +
    "inner join orgs o on s.org_id = o.id " +
    "inner join platforms p on o.platform_id = p.id " +
    "where o.name = :eai"
  if (!filter.app.isNullOrBlank()) { sql += " and lower(a.name) = lower(:app)" }
  if (!filter.state.isNullOrBlank()) { sql += " and lower(a.state) = lower(:state)" }
  sql += " order by p.name,s.name"
  val query = em.createNativeQuery(sql)
  query.setParameter("eai",filter.eai)
  if (!filter.app.isNullOrBlank()) { query.setParameter("app",filter.app) }
  if (!filter.state.isNullOrBlank()) { query.setParameter("state",filter.state) }
  @Suppress("UNCHECKED_CAST")
  return query.resultList as List<Deployment>
}

尽管代码可以运行并执行,但是好像Spring(或Kotlin)不再自动将Java List 转换为Kotlin List。

当我使用方法1 将List 转换为JSON时,我正确地看到:

{
  "eai": "6949","deployments": [
    {
      "app": "CisBidLine","platform": "edcbo1","instances": 3,"org": "6949","state": "STARTED","space": "production"
    },...

但是,对于方法2 ,部署数据被视为数组而不是对象:

{
  "eai": "6949","deployments": [
    [
      "CisPicture","edcbo1","6949","production",1,"STARTED"
    ],...

两种方法间的环境或逻辑没有区别,除了一种方法是使用@Query明确使用另一种em.createNativeQuery。

任何帮助将不胜感激!

更新

如果我理解正确,只要地图的 属性匹配,Kotlin就可以将地图有效地转换为界面 。因为 query.resultList 返回 List ,所以诀窍可能是将其转换为使用别名作为键进行映射。在引擎盖下使用Hibernate时,我发现以下工作有效:

query
.unwrap(org.hibernate.query.NativeQuery::class.java)
.setResultTransformer(org.hibernate.transform.Transformers.ALIAS_TO_ENTITY_MAP)

现在我可以使用:

@Suppress("UNCHECKED_CAST")
return query.resultList as List<Deployment>

对于那些不使用Hibernate的用户,我假设可以先将List手动转换为Map,然后使用 as List 进行转换。

我愿意接受其他方法,但这似乎是有道理的!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)