You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Java SQL构建器返回的util.Map转为Seq[anorm.NamedParameter]

Convert Java util.Map<String, AnyRef> to Anorm Seq[NamedParameter]

Here's a robust solution that handles null values, Java collections, and leverages Anorm's built-in implicit conversions to avoid manual type matching for every possible data type:

Step 1: Import Required Packages

First, make sure you have these imports in scope to handle Java/Scala collection conversions and Anorm's utilities:

import scala.jdk.CollectionConverters._
import anorm._

Step 2: Create a Conversion Utility

Build a helper object to encapsulate the conversion logic. This will handle edge cases like nulls, Java collections, and Java wrapper types (e.g., java.lang.Integer, java.lang.Boolean):

object AnormJavaParamConverter {
  // Convert Java Map directly to Anorm NamedParameters
  def toNamedParams(javaMap: java.util.Map[String, AnyRef]): Seq[NamedParameter] = {
    javaMap.asScala.map { case (paramName, paramValue) =>
      paramName -> convertValue(paramValue)
    }.toSeq
  }

  private def convertValue(value: AnyRef): ParameterValue = value match {
    // Handle null values directly (maps to SQL NULL)
    case null => ParameterValue.Null

    // Convert Java collections to Scala collections for Anorm compatibility
    case javaColl: java.util.Collection[_] =>
      ParameterValue(javaColl.asScala)

    // Handle Java arrays
    case arr: Array[_] => ParameterValue(arr)

    // Handle Scala Option (if your Java builder ever returns these)
    case opt: Option[_] => ParameterValue(opt)

    // Handle Java wrapper types by unboxing to Scala primitives
    case javaBool: java.lang.Boolean => ParameterValue(javaBool.booleanValue())
    case javaInt: java.lang.Integer => ParameterValue(javaInt.intValue())
    case javaLong: java.lang.Long => ParameterValue(javaLong.longValue())
    case javaDouble: java.lang.Double => ParameterValue(javaDouble.doubleValue())
    case javaFloat: java.lang.Float => ParameterValue(javaFloat.floatValue())

    // Fallback to Anorm's built-in implicit conversions for all other types
    case other => implicitly[ParameterValue](other)
  }
}

Step 3: Use the Converter in Your Code

Once you have the utility, integrate it with your Anorm SQL call like this:

// Get results from your Java SQL builder
val sqlQuery: String = yourJavaBuilder.buildQuery()
val javaParams: java.util.Map[String, AnyRef] = yourJavaBuilder.buildParameters()

// Convert to Anorm-compatible NamedParameters
val anormParams = AnormJavaParamConverter.toNamedParams(javaParams)

// Execute the query
val result = SQL(sqlQuery).on(anormParams: _*).executeQuery()

Key Advantages Over Manual Type Matching

  • No manual type exhaustive checks: We rely on Anorm's existing implicit conversions for most types (Strings, Dates, Scala primitives, etc.), so you don't have to update the code every time you add a new data type.
  • Null handling: Explicitly maps Java null to Anorm's ParameterValue.Null, which correctly translates to SQL NULL.
  • Collection support: Automatically converts Java collections (e.g., ArrayList, HashSet) to Scala collections that Anorm can process (works with IN clauses if your database driver supports array parameters).
  • Java wrapper type support: Unboxes Java's wrapper types (like java.lang.Integer) to their Scala primitive equivalents, which Anorm handles seamlessly.

Notes

  • If you encounter a custom type that Anorm doesn't support, you can add a specific case to convertValue or define a custom implicit ParameterValue conversion for that type.
  • For database-specific collection handling (e.g., PostgreSQL arrays), ensure your JDBC driver supports passing collection/array parameters.

内容的提问来源于stack exchange,提问作者Bublik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:19:02