Skip to content

Commit

Permalink
Object Field/Method arguments: use generic type to capture things lik…
Browse files Browse the repository at this point in the history
…e List<T>

Hopefully fixes #1784
  • Loading branch information
stevenschlansker committed Nov 21, 2020
1 parent 4f14361 commit 9fe909a
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 9 deletions.
Expand Up @@ -41,7 +41,7 @@ public class ObjectFieldArguments extends ObjectPropertyNamedArgumentFinder {
JdbiCaches.declare((config, beanClass) ->
Stream.of(beanClass.getFields())
.collect(Collectors.toMap(Field::getName, f -> {
QualifiedType<?> qualifiedType = QualifiedType.of(f.getType())
QualifiedType<?> qualifiedType = QualifiedType.of(f.getGenericType())
.withAnnotations(config.get(Qualifiers.class).findFor(f));
Function<Object, Object> getter = Unchecked.function(
Unchecked.function(MethodHandles.lookup()::unreflectGetter).apply(f)::invoke);
Expand Down
Expand Up @@ -60,7 +60,7 @@ private static Map<String, Function<Object, TypedValue>> load(ConfigRegistry con
Function.identity(),
ObjectMethodArguments::bridgeMethodMerge))
.forEach((name, method) -> {
QualifiedType<?> qualifiedType = QualifiedType.of(method.getReturnType())
QualifiedType<?> qualifiedType = QualifiedType.of(method.getGenericReturnType())
.withAnnotations(config.get(Qualifiers.class).findFor(method));
MethodHandle mh = Unchecked.function(MethodHandles.lookup()::unreflect).apply(method);
methodMap.put(name, Unchecked.function(
Expand Down
15 changes: 13 additions & 2 deletions core/src/main/java/org/jdbi/v3/core/h2/H2DatabasePlugin.java
Expand Up @@ -26,7 +26,18 @@ public class H2DatabasePlugin extends JdbiPlugin.Singleton {
@Override
public void customizeJdbi(Jdbi db) {
db.setSqlArrayArgumentStrategy(SqlArrayArgumentStrategy.OBJECT_ARRAY);
db.registerArrayType(UUID.class, "uuid");
db.registerArrayType(int.class, "integer");
db.registerArrayType(UUID.class, "uuid")
.registerArrayType(short.class, "smallint")
.registerArrayType(Short.class, "smallint")
.registerArrayType(int.class, "integer")
.registerArrayType(Integer.class, "integer")
.registerArrayType(long.class, "bigint")
.registerArrayType(Long.class, "bigint")
.registerArrayType(String.class, "varchar")
.registerArrayType(UUID.class, "uuid")
.registerArrayType(float.class, "float4")
.registerArrayType(Float.class, "float4")
.registerArrayType(double.class, "float8")
.registerArrayType(Double.class, "float8");
}
}
Expand Up @@ -113,6 +113,7 @@ private void generate(Element sqlObjE) throws IOException {
.forEach(implSpec::addMethod);

final TypeSpec.Builder onDemand = TypeSpec.classBuilder("OnDemand");
onDemand.addSuperinterface(SqlObject.class);
onDemand.addModifiers(Modifier.PUBLIC, Modifier.STATIC);
onDemand.addField(Jdbi.class, "db", Modifier.PRIVATE, Modifier.FINAL);
onDemand.addMethod(MethodSpec.constructorBuilder()
Expand Down Expand Up @@ -194,10 +195,11 @@ private MethodSpec generateMethod(TypeSpec.Builder typeBuilder, CodeBlock.Builde
private MethodSpec generateOnDemand(TypeElement sqlObjectType, ExecutableElement method) {
return MethodSpec.overriding(method)
.addCode(CodeBlock.builder()
.add("$L db.$L($T.class, e -> e.$L($L));\n",
.add("$L db.$L($T.class, e -> (($L) e).$L($L));\n",
method.getReturnType().getKind() == TypeKind.VOID ? "" : ("return (" + method.getReturnType().toString() + ")"), // NOPMD
method.getReturnType().getKind() == TypeKind.VOID ? "useExtension" : "withExtension",
sqlObjectType.asType(),
sqlObjectType.getSimpleName() + "Impl",
method.getSimpleName(),
paramList(method))
.build())
Expand Down
@@ -0,0 +1,88 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jdbi.v3.generator;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import org.jdbi.v3.core.Handle;
import org.jdbi.v3.core.rule.H2DatabaseRule;
import org.jdbi.v3.sqlobject.GenerateSqlObject;
import org.jdbi.v3.sqlobject.config.RegisterConstructorMapper;
import org.jdbi.v3.sqlobject.customizer.BindFields;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.SqlUpdate;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class ArrayBindingTest {
@Rule
public H2DatabaseRule dbRule = GeneratorH2Rule.rule();

private Handle handle;
private BazDao dao;

@Before
public void setUp() {
handle = dbRule.getSharedHandle();
handle.execute("create table baz (baz array)");
dao = handle.attach(BazDao.class);
}

@Test
public void simpleGeneratedClass() {
final Baz baz1 = new Baz(1, 2, 3);
dao.insert(baz1);
final Baz baz2 = new Baz(2, 3, 4);
dao.insert(baz2);

assertThat(dao.list())
.containsExactlyInAnyOrder(baz1, baz2);
}

@GenerateSqlObject
@RegisterConstructorMapper(Baz.class)
interface BazDao {
@SqlUpdate("insert into baz (baz) values (:baz)")
void insert(@BindFields Baz value);

@SqlQuery("select baz from baz")
List<Baz> list();
}

public static class Baz {
public Baz(final int... baz) {
this.baz = IntStream.of(baz)
.boxed()
.collect(Collectors.toList());
}

public final List<Integer> baz;

@Override
public int hashCode() {
return baz.hashCode();
}

@Override
public boolean equals(final Object obj) {
return obj instanceof Baz && Objects.equals(((Baz) obj).baz, baz);
}
}
}
28 changes: 28 additions & 0 deletions generator/src/test/java/org/jdbi/v3/generator/GeneratorH2Rule.java
@@ -0,0 +1,28 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jdbi.v3.generator;

import org.jdbi.v3.core.extension.Extensions;
import org.jdbi.v3.core.h2.H2DatabasePlugin;
import org.jdbi.v3.core.rule.H2DatabaseRule;
import org.jdbi.v3.sqlobject.SqlObjectPlugin;

public class GeneratorH2Rule {
public static H2DatabaseRule rule() {
return new H2DatabaseRule()
.withPlugin(new H2DatabasePlugin())
.withPlugin(new SqlObjectPlugin())
.withConfig(Extensions.class, c -> c.setAllowProxy(false));
}
}
Expand Up @@ -27,12 +27,10 @@
import org.jdbi.v3.core.Something;
import org.jdbi.v3.core.config.ConfigRegistry;
import org.jdbi.v3.core.config.JdbiConfig;
import org.jdbi.v3.core.extension.Extensions;
import org.jdbi.v3.core.mapper.SomethingMapper;
import org.jdbi.v3.core.rule.H2DatabaseRule;
import org.jdbi.v3.sqlobject.GenerateSqlObject;
import org.jdbi.v3.sqlobject.SqlObject;
import org.jdbi.v3.sqlobject.SqlObjectPlugin;
import org.jdbi.v3.sqlobject.config.Configurer;
import org.jdbi.v3.sqlobject.config.ConfiguringAnnotation;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
Expand All @@ -45,8 +43,7 @@

public class NonpublicSubclassTest {
@Rule
public H2DatabaseRule dbRule = new H2DatabaseRule().withPlugin(new SqlObjectPlugin()).withSomething()
.withConfig(Extensions.class, c -> c.setAllowProxy(false));
public H2DatabaseRule dbRule = GeneratorH2Rule.rule().withSomething();

private Handle handle;
private AbstractClassDao dao;
Expand Down
Expand Up @@ -113,6 +113,8 @@ public void customizeJdbi(Jdbi jdbi) {
jdbi.registerArgument(new BlobInputStreamArgumentFactory());
jdbi.registerArgument(new ClobReaderArgumentFactory());

jdbi.registerArrayType(short.class, "smallint");
jdbi.registerArrayType(Short.class, "smallint");
jdbi.registerArrayType(int.class, "integer");
jdbi.registerArrayType(Integer.class, "integer");
jdbi.registerArrayType(long.class, "bigint");
Expand Down
Expand Up @@ -29,6 +29,7 @@
import org.jdbi.v3.core.internal.exceptions.Sneaky;
import org.jdbi.v3.sqlobject.GenerateSqlObject;
import org.jdbi.v3.sqlobject.Handler;
import org.jdbi.v3.sqlobject.SqlObject;
import org.jdbi.v3.sqlobject.UnableToCreateSqlObjectException;

public final class SqlObjectInitData {
Expand Down Expand Up @@ -77,6 +78,11 @@ private static Method lookupMethod(Class<?> klass, String methodName, Class<?>..
return klass.getDeclaredMethod(methodName, parameterTypes);
} catch (Exception x) {
e.addSuppressed(x);
try {
return SqlObject.class.getMethod(methodName, parameterTypes);
} catch (Exception x2) {
e.addSuppressed(x2);
}
}
throw new IllegalStateException(
String.format("can't find %s#%s%s", klass.getName(), methodName, Arrays.asList(parameterTypes)), e);
Expand Down

0 comments on commit 9fe909a

Please sign in to comment.