/** * Obtain a column mapper for the given type. * * @param type the target type to map to * @return a ColumnMapper for the given type, or empty if no column mapper is registered for the given type. */ public Optional<ColumnMapper<?>> findFor(Type type) { return findFor(QualifiedType.of(type)).map(m -> (ColumnMapper<?>) m); }
/** * Creates a {@code QualifiedType<T>} for a {@code GenericType<T>} with no qualifiers. * @param type the unqualified type * @return the unqualified QualifiedType * @see #with(Annotation...) to then qualify your type */ @SuppressWarnings("unchecked") public static <T> QualifiedType<T> of(GenericType<T> type) { return (QualifiedType<T>) of(type.getType()); }
ConsumerResultReturner(Method method, int consumerIndex) { this.consumerIndex = consumerIndex; Type parameterType = method.getGenericParameterTypes()[consumerIndex]; this.elementType = QualifiedType.of( GenericTypes.findGenericParameter(parameterType, Consumer.class) .orElseThrow(() -> new IllegalStateException( "Cannot reflect Consumer<T> element type T in method consumer parameter " + parameterType))) .with(getQualifiers(method.getParameters()[consumerIndex])); }
JpaMember(Class<?> clazz, Column column, Field field) { this.clazz = requireNonNull(clazz); this.columnName = nameOf(column, field.getName()); this.qualifiedType = QualifiedType.of(field.getGenericType()).with(getQualifiers(field)); field.setAccessible(true); this.accessor = field::get; this.mutator = field::set; }
/** * Bind a {@code String} argument positionally, as {@code NVARCHAR} type. * * @param position position to bind the parameter at, starting at 0 * @param value to bind * * @return the same Query instance */ @Beta public final This bindNVarchar(int position, String value) { return bind(position, toArgument(QualifiedType.of(String.class).with(NVarchar.class), value)); }
@Test public void testConflictingSourceAnnotations() { assertThatThrownBy(() -> db.getJdbi().getConfig(EnumStrategies.class).findStrategy(QualifiedType.of(BiPolar.class))) .isInstanceOf(IllegalArgumentException.class); }
@Benchmark public List<Tribble> mapByOrdinal() { return jdbi.withHandle(h -> h.select("select ordinal from ordinals") .mapTo(QualifiedType.of(Tribble.class).with(EnumByOrdinal.class)) .list()); }
@Test public void testReadsViaFluentAPI() { List<Map<String, String>> caps = handle.createQuery("select caps from campaigns order by id") .mapTo(QualifiedType.of(STRING_MAP).with(HStore.class)) .list(); assertThat(caps).isEqualTo(ImmutableList.of( ImmutableMap.of("yearly", "10000", "monthly", "5000", "daily", "200"), ImmutableMap.of("yearly", "1000", "monthly", "200", "daily", "20") )); }
@Test public void testConflictingQualifiers() { QualifiedType<RetentionPolicy> type = QualifiedType.of(RetentionPolicy.class).with(EnumByName.class, EnumByOrdinal.class); assertThatThrownBy(() -> db.getJdbi().getConfig(EnumStrategies.class).findStrategy(type)) .isInstanceOf(IllegalArgumentException.class); }
@Test public void methodCallOverridesClassForOrdinal() { Object byOrdinal = h.createQuery("select :ordinal") .bind("ordinal", ByName.ALPHABETIC.ordinal()) .mapTo(QualifiedType.of(ByName.class).with(EnumByOrdinal.class)) .findOnly(); assertThat(byOrdinal) .isEqualTo(ByName.ALPHABETIC); }
@Test public void qualifiedTypeShouldBePersistent() { StatementContext context = StatementContextAccess.createContext(); // it's about the return type being String and not ? @SuppressWarnings("unused") Optional<ColumnMapper<String>> mapper = context.findColumnMapperFor(QualifiedType.of(String.class).with(NVarchar.class)); }
@Test public void testHandlesEmptyMap() { handle.execute("insert into campaigns(id, caps) values (?,?)", 4, ImmutableMap.of()); Map<String, String> newCaps = handle.createQuery("select caps from campaigns where id=?") .bind(0, 4) .mapTo(QualifiedType.of(STRING_MAP).with(HStore.class)) .findOnly(); assertThat(newCaps).isEmpty(); }
@Test public void testWritesViaFluentApi() { handle.createUpdate("insert into campaigns(id, caps) values (:id, :caps)") .bind("id", 3) .bindByType("caps", caps, QualifiedType.of(STRING_MAP).with(HStore.class)) .execute(); Map<String, String> newCaps = handle.createQuery("select caps from campaigns where id=?") .bind(0, 3) .mapTo(QualifiedType.of(STRING_MAP).with(HStore.class)) .findOnly(); assertThat(newCaps).isEqualTo(caps); }
@Test public void methodCallCanBeAnnotatedAsByName() { h.getConfig(Enums.class).setEnumStrategy(EnumStrategy.BY_ORDINAL); Object byName = h.createQuery("select :name") .bind("name", Foobar.FOO.name()) .mapTo(QualifiedType.of(Foobar.class).with(EnumByName.class)) .findOnly(); assertThat(byName) .isEqualTo(Foobar.FOO); }
@Test public void methodCallOverridesClassForName() { h.getConfig(Enums.class).setEnumStrategy(EnumStrategy.BY_ORDINAL); Object byName = h.createQuery("select :name") .bind("name", ByOrdinal.NUMERIC.name()) .mapTo(QualifiedType.of(ByOrdinal.class).with(EnumByName.class)) .findOnly(); assertThat(byName) .isEqualTo(ByOrdinal.NUMERIC); }
@Test public void testHandlesNulls() { handle.execute("insert into campaigns(id, caps) values (?,?)", 4, null); Map<String, String> newCaps = handle.createQuery("select caps from campaigns where id=?") .bind(0, 4) .mapTo(QualifiedType.of(STRING_MAP).with(HStore.class)) .findOnly(); assertThat(newCaps).isNull(); }
@Test public void registerColumnMapperFactory() { dbRule.getJdbi() .registerColumnMapper(new ReversedStringMapperFactory()) .useHandle(handle -> { handle.execute("insert into something (id, name) values (1, 'xyz')"); assertThat( handle.select("SELECT name FROM something") .mapTo(QualifiedType.of(String.class).with(Reversed.class)) .findOnly()) .isEqualTo("zyx"); }); }
@Test public void configColumnMappersRegisterFactory() { dbRule.getJdbi() .configure(ColumnMappers.class, config -> config.register(new ReversedStringMapperFactory())) .useHandle(handle -> { handle.execute("insert into something (id, name) values (1, 'xyz')"); assertThat( handle.select("SELECT name FROM something") .mapTo(QualifiedType.of(String.class).with(Reversed.class)) .findOnly()) .isEqualTo("zyx"); }); }
@Test public void testRaisesExceptionWhenReadsWithWrongType() { expectedException.expect(NoSuchMapperException.class); expectedException.expectMessage("No mapper registered for type @org.jdbi.v3.postgres.HStore() java.util.Map<java.lang.String, java.lang.Object>"); handle.createQuery("select caps from campaigns order by id") .mapTo(QualifiedType.of(new GenericType<Map<String, Object>>() {}).with(HStore.class)) .list(); }
@Test public void methodCallOverridesClassForOrdinal() { db.getJdbi().useHandle(h -> { h.createUpdate("create table enums(id int, ordinal int)").execute(); h.createUpdate("insert into enums(id, ordinal) values(1, :ordinal)") .bindByType("ordinal", ByName.ALPHABETIC, QualifiedType.of(ByName.class).with(EnumByOrdinal.class)) .execute(); Integer inserted = h.createQuery("select ordinal from enums") .mapTo(Integer.class) .findOnly(); assertThat(inserted).isEqualTo(ByName.ALPHABETIC.ordinal()); }); }