一种绑定Java映射的方法<;字符串,对象>;到JDBI INSERT语句中的sql varchar
在JDBI@BindBean注释中,有没有一种方法可以将java一种绑定Java映射的方法<;字符串,对象>;到JDBI INSERT语句中的sql varchar,java,sql,jdbi,Java,Sql,Jdbi,在JDBI@BindBean注释中,有没有一种方法可以将javaMap绑定到varchar 例如,我有一个classSomething.class,我创建了一个 @SqlBatch(“插入到某物(名称、负载)值(:名称、负载)”) 现在在我的java类中,name是String类型,payload是Map类型,我希望在DB表中类型是varchar(…)。现在我想把Map对象作为一个JSON对象插入到列中,这是不是可以通过创建我自己的复杂绑定器来实现的,如中所定义的?而不是让我的负载在java中是
Map
绑定到varchar
例如,我有一个classSomething.class
,我创建了一个
@SqlBatch(“插入到某物(名称、负载)值(:名称、负载)”)
现在在我的java类中,
name
是String
类型,payload
是Map
类型,我希望在DB表中类型是varchar(…)
。现在我想把Map
对象作为一个JSON对象插入到列中,这是不是可以通过创建我自己的复杂绑定器来实现的,如中所定义的?而不是让我的负载在java中是String类型 修复了中建议的创建ArgumentFactory活页夹的问题
因此,我需要创建一个只包含一个类型为Map
的字段的类,从org.skife.jdbi.v2.tweak实现arumment
接口
public class NotificationPayloadArgument implements Argument {
private NotificationPayload payload;
NotificationPayloadArgument(NotificationPayload payload) {
this.payload = payload;
}
@Override
public void apply(int i, PreparedStatement preparedStatement, StatementContext statementContext)
throws SQLException {
preparedStatement.setString(i, toString());
}
@Override
public String toString() {
return new JSONObject(payload).toString();
}
}
为了完成这项工作,我当然需要实现一个Factory类,该类使用我新创建的类型实现org.skife.jdbi.v2.tweak.ArgumentFactory
接口,因此工厂最终是这样的:
public class NotificationPayloadFactory implements ArgumentFactory<NotificationPayload> {
@Override
public boolean accepts(Class<?> expectedType, Object value, StatementContext ctx) {
return value instanceof NotificationPayload;
}
@Override
public Argument build(Class<?> expectedType, NotificationPayload value, StatementContext ctx) {
return value;
}
}
我试着用一个工厂来制作一张地图
,但没能做到这一点,NPE有风险
编辑
我之所以在NotificationPayload
中重写toString()
,是因为我需要json格式的有效负载,在某些地方我需要字符串对象。但也可以删除它,然后在调用toString()
的preparedStatement.setString()
中使用新的JSONObject(有效负载).toString()
。公共类映射参数实现参数{
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);
}
}
专用地图有效载荷;
私有对象映射器对象映射器;
公共映射参数(ObjectMapper ObjectMapper,映射负载){
this.objectMapper=objectMapper;
这个有效载荷=有效载荷;
}
@凌驾
public void apply(inti、PreparedStatement语句、StatementContext语句)引发SQLException{
试一试{
statement.setString(i,objectMapper.writeValueAsString(有效负载));
}捕获(JsonProcessingException e){
log.info(“未能序列化有效负载”,e);
}
}
}
公共类MapArgumentFactory实现ArgumentFactory{
私有对象映射器映射器;
公共MapArgumentFactory(ObjectMapper映射器){
this.mapper=mapper;
}
@凌驾
公共布尔接受(类类型、对象值、语句上下文语句上下文){
映射的返回值实例;
}
@凌驾
公共参数生成(类类型、映射映射、语句上下文语句上下文){
返回新的映射参数(映射器、映射);
}
}
然后将地图转换为JSON对象,正如您所说的x)检查我不能这样做,Nathan,因为我需要它作为其他东西的地图。但无论如何,谢谢你的建议。如果你试图将地图存储在一行中,它显然设计得不好。。。每个键/值应以一行的形式存储在辅助表中,链接到Something.name
(或每个name+playload\u键一行)。由此,可以很容易地迭代映射以创建每一行,但也可以很容易地获得用于构建映射的行。无需将地图解析为某些格式的字符串
sort@AxelH谢谢-是的,这是一个糟糕的设计,但我现在不允许改变它,因为如果改变它将打破许多传统的东西,这是我们目前不允许做的。首先,当我们摆脱了所有遗留的东西,我可以做任何我想做的改变:)。但是我发现了这一点,所以我要尝试做一些全局绑定,看看它是否有效:)。我认为它应该是地图的值实例,如这里所述@arpitagaral你是对的,我编辑了我的答案,使之正确,所以现在value instanceof NotificationPayload
是正确的。现在它看起来是正确的,你也可以参考我的答案。
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);
}
}