use of org.jdbi.v3.core.statement.StatementContext in project jdbi by jdbi.
the class BeanMapper method specialize0.
private RowMapper<T> specialize0(ResultSet rs, StatementContext ctx, List<String> columnNames, List<ColumnNameMatcher> columnNameMatchers, List<String> unmatchedColumns) throws SQLException {
final List<RowMapper<?>> mappers = new ArrayList<>();
final List<PropertyDescriptor> properties = new ArrayList<>();
for (PropertyDescriptor descriptor : info.getPropertyDescriptors()) {
Nested anno = Stream.of(descriptor.getReadMethod(), descriptor.getWriteMethod()).filter(Objects::nonNull).map(m -> m.getAnnotation(Nested.class)).filter(Objects::nonNull).findFirst().orElse(null);
if (anno == null) {
String paramName = prefix + paramName(descriptor);
findColumnIndex(paramName, columnNames, columnNameMatchers, () -> debugName(descriptor)).ifPresent(index -> {
Type type = descriptor.getReadMethod().getGenericReturnType();
ColumnMapper<?> mapper = ctx.findColumnMapperFor(type).orElse((r, n, c) -> r.getObject(n));
mappers.add(new SingleColumnMapper<>(mapper, index + 1));
properties.add(descriptor);
unmatchedColumns.remove(columnNames.get(index));
});
} else {
String nestedPrefix = prefix + anno.value();
RowMapper<?> nestedMapper = nestedMappers.computeIfAbsent(descriptor, d -> new BeanMapper<>(d.getPropertyType(), nestedPrefix)).specialize0(rs, ctx, columnNames, columnNameMatchers, unmatchedColumns);
mappers.add(nestedMapper);
properties.add(descriptor);
}
}
if (mappers.isEmpty() && columnNames.size() > 0) {
throw new IllegalArgumentException(String.format("Mapping bean type %s " + "didn't find any matching columns in result set", type));
}
return (r, c) -> {
T bean = construct();
for (int i = 0; i < mappers.size(); i++) {
RowMapper<?> mapper = mappers.get(i);
PropertyDescriptor property = properties.get(i);
Object value = mapper.map(r, ctx);
writeProperty(bean, property, value);
}
return bean;
};
}
use of org.jdbi.v3.core.statement.StatementContext in project jdbi by jdbi.
the class DefinedAttributeTemplateEngine method render.
@Override
public String render(String template, StatementContext ctx) {
StringBuilder b = new StringBuilder();
DefineStatementLexer lexer = new DefineStatementLexer(new ANTLRStringStream(template));
try {
Token t = lexer.nextToken();
while (t.getType() != EOF) {
switch(t.getType()) {
case COMMENT:
case LITERAL:
case QUOTED_TEXT:
case DOUBLE_QUOTED_TEXT:
b.append(t.getText());
break;
case DEFINE:
String text = t.getText();
String key = text.substring(1, text.length() - 1);
Object value = ctx.getAttribute(key);
if (value == null) {
throw new UnableToCreateStatementException("Undefined attribute for token '" + text + "'", ctx);
}
b.append(value);
break;
case ESCAPED_TEXT:
b.append(t.getText().substring(1));
break;
default:
break;
}
t = lexer.nextToken();
}
return b.toString();
} catch (RuntimeException e) {
throw new UnableToCreateStatementException("Error rendering SQL template: '" + template + "'", e, ctx);
}
}
use of org.jdbi.v3.core.statement.StatementContext 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.statement.StatementContext in project jdbi by jdbi.
the class MapMapper method specialize.
@Override
public RowMapper<Map<String, Object>> specialize(ResultSet rs, StatementContext ctx) throws SQLException {
ResultSetMetaData m = rs.getMetaData();
int columnCount = m.getColumnCount();
String[] columnNames = new String[columnCount + 1];
for (int i = 1; i <= columnCount; i++) {
String key = m.getColumnName(i);
String alias = m.getColumnLabel(i);
if (alias == null) {
alias = key;
}
if (foldCase) {
alias = alias.toLowerCase(Locale.ROOT);
}
columnNames[i] = alias;
}
return (r, c) -> {
Map<String, Object> row = new LinkedHashMap<>(columnCount);
for (int i = 1; i <= columnCount; i++) {
row.put(columnNames[i], rs.getObject(i));
}
return row;
};
}
use of org.jdbi.v3.core.statement.StatementContext in project jdbi by jdbi.
the class SqlBatchHandler method invoke.
@Override
public Object invoke(Object target, Object[] args, HandleSupplier h) {
final Handle handle = h.getHandle();
final String sql = locateSql(handle);
final int chunkSize = batchChunkSize.call(args);
final Iterator<Object[]> batchArgs = zipArgs(getMethod(), args);
ResultIterator<Object> result;
if (batchArgs.hasNext()) {
result = new ResultIterator<Object>() {
ResultIterator<?> batchResult;
boolean closed = false;
{
// Ensure our batchResult is prepared, so we can get its context
hasNext();
}
@Override
public boolean hasNext() {
if (closed) {
throw new IllegalStateException("closed");
}
// first, any elements already buffered?
if (batchResult != null) {
if (batchResult.hasNext()) {
return true;
}
// no more in this chunk, release resources
batchResult.close();
}
// more chunks?
if (!batchArgs.hasNext()) {
return false;
}
// execute a single chunk and buffer
PreparedBatch batch = handle.prepareBatch(sql);
for (int i = 0; i < chunkSize && batchArgs.hasNext(); i++) {
applyCustomizers(batch, batchArgs.next());
batch.add();
}
batchResult = executeBatch(handle, batch);
// recurse to ensure we actually got elements
return hasNext();
}
@Override
public Object next() {
if (closed) {
throw new IllegalStateException("closed");
}
if (!hasNext()) {
throw new NoSuchElementException();
}
return batchResult.next();
}
@Override
public StatementContext getContext() {
return batchResult.getContext();
}
@Override
public void close() {
closed = true;
batchResult.close();
}
};
} else {
PreparedBatch dummy = handle.prepareBatch(sql);
result = new ResultIterator<Object>() {
@Override
public void close() {
// no op
}
@Override
public StatementContext getContext() {
return dummy.getContext();
}
@Override
public boolean hasNext() {
return false;
}
@Override
public Object next() {
throw new NoSuchElementException();
}
};
}
ResultIterable<Object> iterable = ResultIterable.of(result);
return magic.mappedResult(iterable, result.getContext());
}
Aggregations