微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决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 进行转换。

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。