下午好。
我正在尝试将带有字符串的列表绑定到IN运算符使用的查询。 我正在使用Oracle。 我按照链接描述的示例进行了操作: How to use IN operator with JDBI?
<input type="text" placeholder="From" class="week" id="dt1">
<input type="text" placeholder="To" disabled="disabled" class="week" id="dt2">
$(function() {
$("#dt1").datepicker({
minDate: "-",
maxViewMode: "weeks",
format: "dd-mm-yy",
clearBtn: true,
}).on('changeDate', function(event) {
$('#dt2').removeAttr('disabled'); //We enable our #To Picker
var newDate = new Date(event.date);
newDate.setDate(newDate.getDate() + 6); //We add 6 days to our selected date
$("#dt2").datepicker("setStartDate", event.date); //Set as start point that selected day
$("#dt2").datepicker("setEndDate", newDate); //Set the final "MaxDate
});
//We do the same for this one but backwards to avoid puttin "invalid" dates
$("#dt2").datepicker({
minDate: 0,
format: 'dd-mm-yyyy',
endDate: "today"
}).on('changeDate', function(event) {
var newDate = new Date(event.date);
newDate.setDate(newDate.getDate() - 6);
//You can alway remove this line to allow your user to select any start date
$("#dt1").datepicker("setStartDate", newDate);
//And here we set our max date on From picker so he doesn't again enter "invalid" dates
$("#dt1").datepicker("setEndDate", event.date);
});
});
我创建了一个ListArgumentFactory
List<String> ms = new ArrayList();
ms.add("Novosibirsk");
ms.add("Perm");
public interface CityDAO {
@RegisterMapper(CitiesMapper.class)
@SqlQuery("SELECT *
FROM Universities
WHERE Location IN (:cities)")
List<cities> getItems(@Bind("cities") List<String> cities);}
}
我注册了工厂
public class ListArgumentFactory implements ArgumentFactory<List> {
@Override
public boolean accepts(Class<?> expectedType, Object value, StatementContext ctx) {
return value instanceof List;
}
@Override
public Argument build(Class<?> expectedType, final List value, StatementContext ctx) {
return new Argument() {
@Override
public void apply(int position, PreparedStatement statement, StatementContext ctx) throws SQLException {
String type = null;
if(value.get(0).getClass() == String.class){
type = "varchar";
} else if(value.get(0).getClass() == Integer.class){
// For integer and so on...
} else {
// throw error.. type not handled
}
Array array = ctx.getConnection().createArrayOf(type, value.toArray());
statement.setArray(position, array);
}
};
}
}
但是当我提出请求时,我得到了一个异常
public class DBI extends AbstractModule {
private DBI dbi;
@Override
protected void configure() {
this.dbi = new DBI(provideConfig().url());
this.dbi.registerArgumentFactory(new ListArgumentFactory());
}
}
帮我弄清楚我做错了什么
答案 0 :(得分:0)
根据JDBI documentation,使用Oracle实现类似的功能可能非常复杂,因此使用所描述的第一种方法(UseStringTemplate3StatementLocator)可能更好:
Oracle支持类似的东西,但您需要使用Oracle特定的API和oracle.sql.ARRAY实例。在Oracle的情况下,您必须首先在数据库中预先声明数组类型,并在将数组存储在数据库中时,在调用后将其释放。
话虽如此,有一种简单的方法可以用来在Oracle中完成这项工作,即用逗号连接列表中的元素。我使用Java 8 String.join方法修改了ListArgumentFactory:
public class ListArgumentFactory implements ArgumentFactory<List> {
@Override
public boolean accepts(Class<?> expectedType, Object value, StatementContext ctx) {
return value instanceof List;
}
@Override
public Argument build(Class<?> expectedType, final List value, StatementContext ctx) {
return new Argument() {
@Override
public void apply(int position, PreparedStatement statement, StatementContext ctx) throws SQLException {
statement.setString(position, String.join(",", value));
}
};
}
}
我已经尝试过JDBI文档中描述的方法,在Oracle DB中使用oracle.sql.ARRAY和自定义TYPE,但对我来说并不成功。