如何将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
nullto Anorm'sParameterValue.Null, which correctly translates to SQLNULL. - 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
convertValueor define a custom implicitParameterValueconversion for that type. - For database-specific collection handling (e.g., PostgreSQL arrays), ensure your JDBC driver supports passing collection/array parameters.
内容的提问来源于stack exchange,提问作者Bublik
相关产品推荐
相关产品推荐

