1

NamedParameterJdbcTemplate.batchUpdate() takes a Map<String,Object>[] for the list of parameters. I can't figure out how to instantiate the array in a way that doesn't get flagged with a "generic instantiation" error, or an "unchecked assignment" warning. I really wish Spring accepted a List of Maps instead of an array.

Yes I've read: How does one instantiate an array of maps in Java?

However, I don't control the spring-batch NamedParameterJdbcTemplate interface, so I can't change the signature of the batchUpdate() method.

I have a List<Map<String,Object>> named params.

I have tried the following:

namedParameterJdbcTemplate.batchUpdate(
    sql,
    params.toArray(new Map<String,Object[0]) //generic instantiation error
); 

namedParameterJdbcTemplate.batchUpdate(
    sql,
    params.toArray(new Map[0]) //unchecked assignment warning
); 

Full code:

class MyItemWriter implements ItemWriter<MyRecord> {
   @Autowired
   private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

   public void write(List<? extends MyRecord> items) {
      String sql = MyRecord.UPDATE_SQL;
      List<Map<String,Object>> params 
      = items.stream()
             .map(record->new MapBuilder<String,Object>()
                   .put("param1",record.getField1())
                   .put("param2",record.getField2())
                   .build())
             .collect(Collectors.toList());
      namedParameterJdbcTemplate.batchUpdate(
          sql,
          params.toArray(new Map<String,Object>[0]) //generic instantiation error
      );
      namedParameterJdbcTemplate.batchUpdate(
          sql,
          params.toArray(new Map[0]) //unchecked assignment warning.
      );
   }
}
dsharp
  • 95
  • 8

1 Answers1

0

In java, you cannot create an array of Map<String, Object>.

REF: https://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#createArrays

So you create a Map[] then cast it to Map<String, Object>[] with the "unchecked cast" warning. Such a warning is suppressible. JDK EXAMPLE: https://github.com/AdoptOpenJDK/openjdk-jdk14/blob/master/src/java.base/share/classes/java/util/Map.java#L1682:L1689

  namedParameterJdbcTemplate.batchUpdate(sql, toArray(params));


@SuppressWarnings("unchecked")
private static Map<String, ?>[] toArray(List<Map<String, ?>> params) {
    return params.toArray(new Map[0]);
}

NOTE: in your "Full code" example there is no need in collecting to an intermediate List. You can directly allocate the stream to an array. Unfortunately, the parameterless version of Stream's toArray() is still not generic. So you, again, have to use an overloaded toArray(n->new Map[n]) version with the unavoidable, but suppressible warning:

  Map<String,?>[] params = items.stream()
      .map(record -> Map.of(
          "param1",record.getField1(),
          "param2",record.getField2()))
      .toArray(this::newArray);


  @SuppressWarnings("unchecked")
  private Map<String,?>[] newArray(int n) {
    return new Map[n];
  }
epox
  • 9,236
  • 1
  • 55
  • 38