【发布时间】:2014-07-26 21:18:09
【问题描述】:
快速概述,我正在使用 Java Web 框架 Dropwizard 和 PostgreSQL 数据库来学习如何创建 API。 Dropwizard 提供了 JDBI JDBC 包装器来与数据库交互。
TLDR:需要将原生 Postgres UUID 类型与 JDBI 绑定。
SRC:https://github.com/jasonshell/hooktale-api
我遇到的问题是 JDBI 需要 ResultSetMapper 或 ResultSetMapperFactory 以获得更复杂的映射。在我的情况下,这涉及为angler_id拥有一个PostgreSQL uuid。在 AnglerMapper.java 中,rs.getObject("angler_id", java.util.UUID.class) 抛出了一个未在 JDBC 中实现的方法错误。
AnglerMapper.java(导致错误)
package org.sachmo.hooktale.db;
import org.sachmo.hooktale.core.Angler;
import org.skife.jdbi.v2.StatementContext;
import org.skife.jdbi.v2.tweak.ResultSetMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Created by jason on 5/27/14.
* angler mapper
*/
public class AnglerMapper implements ResultSetMapper<Angler> {
@Override
public Angler map(int i, ResultSet rs, StatementContext statementContext) throws SQLException {
return new Angler(rs.getObject("angler_id", java.util.UUID.class), rs.getString("firstName"), rs.getString("lastName"), rs.getString("email"), rs.getString("password"));
}
}
经过一番搜索,我了解到接受 UUID 参数进行绑定的能力不是 JDBI 的属性,而是底层 JDBC 驱动程序。在我的例子中是 org.postgresql.9.3-1100-jdbc41,它能够使用 PreparedStatement.setObject() 接受 UUID,并导致 UUID 的本机绑定在没有 ArgumentFactory 的情况下工作。
我的问题是我不知道如何/在哪里正确实施 PreparedStatement.setObject()。任何关于接受 UUID 参数以与 JDBI 绑定的建议将不胜感激。
如果需要更多信息,包括支持类/接口。
Angler.java
package org.sachmo.hooktale.core;
import io.dropwizard.jackson.JsonSnakeCase;
import java.util.UUID;
/**
* Created by jason on 5/20/14.
* angler
*/
@JsonSnakeCase
public class Angler {
private UUID id;
private String firstName;
private String lastName;
private String email;
private String password;
public Angler(UUID id, String firstName, String lastName, String email, String password) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.password = password;
}
public UUID getId() {
return id;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getFirstName() {
return firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getLastName() {
return lastName;
}
public void setEmail(String email) {
this.email = email;
}
public String getEmail() {
return email;
}
public void setPassword(String password) {
this.password = password;
}
public String getPassword() {
return password;
}
}
AnglerDAO.java
package org.sachmo.hooktale.db;
import org.sachmo.hooktale.core.Angler;
import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
import java.util.List;
import java.util.UUID;
/**
* Created by jason on 5/20/14.
* angler dao
*/
@RegisterMapper(AnglerMapper.class)
public interface AnglerDAO {
@SqlQuery("SELECT * FROM angler ORDER BY created_at")
List<Angler> findAll();
@SqlQuery("SELECT * FROM angler WHERE id = :it")
Angler findById(@Bind UUID id);
}
AnglerResource.java
package org.sachmo.hooktale.resources;
import com.codahale.metrics.annotation.Timed;
import org.sachmo.hooktale.core.Angler;
import org.sachmo.hooktale.db.AnglerDAO;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
import java.util.UUID;
/**
* Created by jason on 5/20/14.
* angler resource
*/
@Path("/angler")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class AnglerResource {
private final AnglerDAO anglerDAO;
public AnglerResource(AnglerDAO anglerDAO) {
this.anglerDAO = anglerDAO;
}
@Path("/{id}")
@GET
@Timed
public Angler getAngler(@PathParam("id")UUID uuid) {
Angler angler = anglerDAO.findById(uuid);
if (angler != null) {
return angler;
} else {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
}
@GET
@Timed
public List<Angler> listAngler() {
return anglerDAO.findAll();
}
}
【问题讨论】:
-
您不想添加数字主键字段并使用它来标识您的对象的任何特殊原因?
-
@condit 在大多数情况下,它只是学习如何使用 JDBI 从 Postgres 中获取 UUID。一个根本原因是我已经读到,与随机 ID 相比,使用数字递增的主键字段(如 BigInt)会使您的应用程序处于易受攻击的位置。例如,如果您有 example.com/users/1000 并且攻击者绕过授权,那么他们可以更容易地枚举用户,而不是随机 UUID。
标签: java postgresql jdbc uuid dropwizard