我最近一直在探索与JDBI捆绑在一起的DropWizard,并很快遇到了同样的问题。不幸的是,JDBI的文档乏善可陈(JavaDoc和它的git存储库中的一些示例单元测试并没有单独解决),这令人失望。
这是我根据示例DAO在JDBI的Sql Object API中实现动态排序的结果:
@UseStringTemplate3StatementLocatorpublic interface ProductsDao { @RegisterMapperFactory(BeanMapperFactory.class) // will map the result of the query to a list of Product POJOs(Beans) @SqlQuery("select * from products order by <orderby> <order> limit :limit offset :offset") List<Product> getProducts(@Define("orderby") String orderBy, @Define("order") String order, @Bind("limit") int limit, @Bind("offset") int offset); @SqlQuery("select count(*) from products") int getProductsCount();}@ UseStringTemplate3StatementLocator-
此注释使我们可以
<arg>在查询中使用语法。这些args将被我们通过
@Define注释提供的任何值替换。
为了能够使用此功能,我还必须将此依赖项添加到我的
pom.xml文件中:
<dependency> <groupId>antlr</groupId> <artifactId>stringtemplate</artifactId> <version>2.3b6</version> <!-- I am not sure if this specific version is meant to be used though --></dependency>
SQL注入警告 应该注意的是,
SqlInjection由于将值直接插入到查询中,因此可以为我们打开大门。(
:arg与
@Bind使用准备好的语句并防止sql注入的查询和注释中的语法相反)。至少您应该清理将用于
@Define字段的参数。(下面是DropWizard的简单示例)。
@Path("/products")@Produces(MediaType.APPLICATION_JSON)public class ProductsResource { private static ImmutableSet<String> orderByChoices = ImmutableSet.of("id", "name", "price", "manufactureDate"); private final ProductsDao dao; public ProductsResource(ProductsDao dao) { this.dao = dao; } @GET // Use @InjectParam to bind many query parameters to a POJO(Bean) instead. // https://jersey.java.net/apidocs/1.17/jersey/com/sun/jersey/api/core/InjectParam.html // i.e. public List<Product> index(@InjectParam ProductsRequest request) // Also use custom Java types for consuming request parameters. This allows to move such validation/sanitization logic outside the 'index' method. // https://jersey.java.net/documentation/1.17/jax-rs.html#d4e260 public List<Product> index(@DefaultValue("id") @QueryParam("orderby") String orderBy, @DefaultValue("asc") @QueryParam("order") String order, @DefaultValue("20") @QueryParam("perpage") IntParam perpage, @DefaultValue("0") @QueryParam("page") IntParam page) int limit, offset; order = order.toLowerCase(); orderBy = orderBy.toLowerCase(); if (!orderByChoices.contains(orderBy)) orderBy = "id"; //sanitize <orderby> if (order != "asc" && order != "desc") order = "asc"; //sanitize <order> limit = perpage.get(); offset = page.get() < 0 ? 0 : page.get() * limit; return dao.getProducts(orderBy, order, limit, offset); }}


