'A way to bind Java Map<String, Object> to sql varchar in JDBI INSERT statement
Is there a way to bind a java Map<String, Object> to a varchar in the the JDBI @BindBean annotation.
So for example I have a class Something.class and I create a
@SqlBatch("INSERT INTO Something (name, payload) VALUES(:name, :payload)").
Now in my java class the name is of type String and payload is of type Map<String, Object> and I want in the DB table the types are varchar(...). Now I want the Map object to be inserted in the column as a JSON object, is that somehow achievable wihtout creating my own complex Binder as defined in http://jdbi.org/sql_object_api_argument_binding/ ? and other than making my payload be of type String in java.
Solution 1:[1]
public class MapArgument implements Argument {
private Map<String, Object> payload;
private ObjectMapper objectMapper;
public MapArgument(ObjectMapper objectMapper, Map<String, Object> payload) {
this.objectMapper = objectMapper;
this.payload = payload;
}
@Override
public void apply(int i, PreparedStatement statement, StatementContext statementContext) throws SQLException {
try {
statement.setString(i, objectMapper.writeValueAsString(payload));
} catch (JsonProcessingException e) {
log.info("Failed to serialize payload ", e);
}
}
}
public class MapArgumentFactory implements ArgumentFactory<Map<String, Object>> {
private ObjectMapper mapper;
public MapArgumentFactory(ObjectMapper mapper) {
this.mapper = mapper;
}
@Override
public boolean accepts(Class<?> type, Object value, StatementContext statementContext) {
return value instanceof Map;
}
@Override
public Argument build(Class<?> type, Map<String, Object> map, StatementContext statementContext) {
return new MapArgument(mapper, map);
}
}
Solution 2:[2]
In kotlin-way using JDBI to insert a data class as JSONB; just create one ArgumentFactory for that datatype and register that factory with JDBI. This is as simple as these 3 lines needed -
internal class CvMetadataArgumentFactory : AbstractArgumentFactory<CvMetadata?>(Types.OTHER) {
override fun build(value: CvMetadata?, config: ConfigRegistry): Argument {
return Argument { position, statement, _ -> statement.setString(position, value?.toString()?:"") }
}
}
Later register this factory -
jdbi.registerArgument(CvMetadataArgumentFactory())
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Arpit Agrawal |
| Solution 2 | mdev |
