使用SQL对象参数绑定(bind)时,JDBI是否可以与UUID参数一起使用?

我有这样的方法:

@SqlQuery("EXECUTE [MyProcedure] :myField")
MyDto myMethod(@Bind("myField") UUID myField);

绑定(bind)到接收如下参数的SQL Server存储过程:
@myField uniqueidentifier

执行时,将抛出此异常:
! com.microsoft.sqlserver.jdbc.SQLServerException: The conversion from UNKNOWN to UNKNOWN is unsupported.
! at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:190)
! at com.microsoft.sqlserver.jdbc.DataTypes.throwConversionError(DataTypes.java:1117)
! at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.setObject(SQLServerPreparedStatement.java:991)

如果我将JDBI上的参数类型更改为String,然后使用UUID对象中的toString()方法调用它,则它将起作用:
@SqlQuery("EXECUTE [MyProcedure] :myField")
MyDto trash(@Bind("myField") String myField);

有没有办法编写我的接受UUID参数的DAO方法,并在绑定(bind)之前将它们转换为字符串?

最佳答案

JDBI仅公开针对JDBC公开其的类型的基于显式类型的绑定(bind)。 JDBC不会公开用于绑定(bind)的UUID类型,因此默认情况下会将其设置为Object。不幸的是,JDBC没有提供显式的UUID绑定(bind)机制,因此遍历String可能是最可移植的方式:-(

如果要在Java中将其绑定(bind)为UUID并在内部将其转换为String,则有两条路径。首先,如果您始终想将UUID绑定(bind)为字符串,则是使用ArgumentFactory,请参见https://github.com/brianm/jdbi/blob/master/src/test/java/org/skife/jdbi/v2/sqlobject/TestRegisterArgumentFactory.java作为示例。

第二种是,如果仅在特定情况下要这样做,则创建一个自定义的活页夹,例如http://jdbi.org/sql_object_api_argument_binding/

使用ArgumentFactory从UUID到字符串的全局绑定(bind)的实现示例:

UUIDArgumentFactory.java:

public class UUIDArgumentFactory implements ArgumentFactory<UUID> {

    @Override
    public boolean accepts(Class<?> expectedType, Object value, StatementContext ctx) {
        return value instanceof UUID;
    }

    @Override
    public Argument build(Class<?> expectedType, UUID value, StatementContext ctx) {
        return new UUIDArgument(value);
    }
}

UUIDArgument.java:
public class UUIDArgument implements Argument {
    private final UUID value;

    public UUIDArgument(UUID value) {
        this.value = value;
    }

    @Override
    public void apply(int position, PreparedStatement statement, StatementContext ctx) throws SQLException {
        statement.setString(position, value.toString());
    }
}

登记:
final DatabaseFactory factory = new DatabaseFactory(environment);
final Database db = factory.build(configuration.getDatabaseConfiguration(), "sqlserver");
db.registerArgumentFactory(new UUIDArgumentFactory());

10-07 19:52
查看更多