use of org.jdbi.v3.core.argument.Argument in project jdbi by jdbi.
the class SqlStatement method bindBeanList.
/**
* Bind a parameter for each value in the given list * number of property names,
* and defines an attribute as the comma-separated list of parameter references (using colon prefix).
*
* Used to create query similar to:
* select * from things where (id, foo) in ((1,'abc'),(2,'def'),(3,'ghi'))
* <p>
* Examples:
* <pre>
*
* List<ThingKey> thingKeys = ...
* List<Thing> things = handle.createQuery("select * from things where (id, foo) in (<thingKeys>)")
* .bindBeanList("thingKeys", thingKeys, Arrays.asList("id", "foo"))
* .mapTo(Contact.class)
* .list();
* </pre>
*
* @param key attribute name
* @param values list of values that will be comma-spliced into the defined attribute value.
* @param propertyNames list of properties that will be invoked on the values.
* @return this
* @throws IllegalArgumentException if the list of values or properties is empty.
* @throws UnableToCreateStatementException If a property can't be found on an value or we can't find a Argument for it.
*/
public final This bindBeanList(String key, List<?> values, List<String> propertyNames) throws UnableToCreateStatementException {
if (values.isEmpty()) {
throw new IllegalArgumentException(getClass().getSimpleName() + ".bindBeanList was called with no values.");
}
if (propertyNames.isEmpty()) {
throw new IllegalArgumentException(getClass().getSimpleName() + ".bindBeanList was called with no properties.");
}
StringBuilder names = new StringBuilder();
StatementContext ctx = getContext();
for (int valueIndex = 0; valueIndex < values.size(); valueIndex++) {
if (valueIndex > 0) {
names.append(',');
}
Object bean = values.get(valueIndex);
BeanPropertyArguments beanProperties = new BeanPropertyArguments(null, bean);
names.append("(");
for (int propertyIndex = 0; propertyIndex < propertyNames.size(); propertyIndex++) {
if (propertyIndex > 0) {
names.append(",");
}
String propertyName = propertyNames.get(propertyIndex);
String name = "__" + key + "_" + valueIndex + "_" + propertyName;
names.append(':').append(name);
Argument argument = beanProperties.find(propertyName, ctx).orElseThrow(() -> new UnableToCreateStatementException("Unable to get " + propertyName + " argument for " + bean, ctx));
bind(name, argument);
}
names.append(")");
}
return define(key, names.toString());
}
use of org.jdbi.v3.core.argument.Argument in project jdbi by jdbi.
the class BindBeanListFactory method createForParameter.
@Override
public SqlStatementParameterCustomizer createForParameter(Annotation annotation, Class<?> sqlObjectType, Method method, Parameter param, int index, Type type) {
final BindBeanList bindBeanList = (BindBeanList) annotation;
final String name = ParameterUtil.findParameterName(bindBeanList.value(), param).orElseThrow(() -> new UnsupportedOperationException("A @BindBeanList parameter was not given a name, " + "and parameter name data is not present in the class file, for: " + param.getDeclaringExecutable() + "::" + param));
return (stmt, arg) -> {
if (arg == null) {
throw new IllegalArgumentException("argument is null; null was explicitly forbidden on BindBeanList");
}
stmt.bindBeanList(name, IterableLike.toList(arg), Arrays.asList(bindBeanList.propertyNames()));
};
}
use of org.jdbi.v3.core.argument.Argument in project jdbi by jdbi.
the class BuiltInArgumentFactory method build.
@Override
@SuppressWarnings("unchecked")
public Optional<Argument> build(Type expectedType, Object value, ConfigRegistry config) {
Class<?> expectedClass = getErasedType(expectedType);
if (value != null && expectedClass == Object.class) {
expectedClass = value.getClass();
}
@SuppressWarnings("rawtypes") ArgBuilder v = BUILDERS.get(expectedClass);
if (v != null) {
return Optional.of(v.build(value));
}
// Enums must be bound as VARCHAR.
if (value instanceof Enum) {
Enum<?> enumValue = (Enum<?>) value;
return Optional.of(STR_BUILDER.build(enumValue.name()));
}
if (value instanceof Optional) {
Object nestedValue = ((Optional<?>) value).orElse(null);
Type nestedType = findOptionalType(expectedType, nestedValue);
return config.get(Arguments.class).findFor(nestedType, nestedValue);
}
return value == null ? Optional.of(config.get(Arguments.class).getUntypedNullArgument()) : Optional.empty();
}
use of org.jdbi.v3.core.argument.Argument in project jdbi by jdbi.
the class SqlArrayArgumentFactory method build.
@Override
public Optional<Argument> build(Type type, Object value, ConfigRegistry config) {
Class<?> erasedType = GenericTypes.getErasedType(type);
if (!(erasedType.isArray() || Collection.class.isAssignableFrom(erasedType))) {
return Optional.empty();
}
if (value == null) {
return Optional.of(new NullArgument(Types.ARRAY));
}
Function<Type, Optional<SqlArrayType<?>>> lookup = eT -> config.get(SqlArrayTypes.class).findFor(eT);
if (erasedType.isArray()) {
Class<?> elementType = erasedType.getComponentType();
return lookup.apply(elementType).map(arrayType -> new SqlArrayArgument<>(arrayType, value));
}
return GenericTypes.findGenericParameter(type, Collection.class).flatMap(lookup).map(arrayType -> new SqlArrayArgument<>(arrayType, value));
}
use of org.jdbi.v3.core.argument.Argument in project jdbi by jdbi.
the class TestBindBean method testNoArgumentFactoryRegisteredForProperty.
@Test
public void testNoArgumentFactoryRegisteredForProperty() {
handle.execute("create table beans (id integer, value_type varchar)");
assertThatThrownBy(() -> handle.attach(BeanDao.class).insert(new Bean(1, ValueType.valueOf("foo")))).hasMessageContaining("No argument factory registered");
}
Aggregations