Jak dostać Optional określonego typu?

0

Chcę wyciągnąć wartość z ResultSeta z bazy ale tak żeby gdy ta wartość jest nullem zwrócić default.
Dlaczego taki kod jest zły?

    protected  <T> T getValueFromResultSet(ResultSet resultSet, String valueName, T defaultValue) {
        try {
            Optional<T> valueOpt = switch (defaultValue.getClass()) {
                case String.class -> Optional.ofNullable(resultSet.getString(valueName));
                case Integer.class -> Optional.ofNullable(resultSet.getInt(valueName));
                // inne typy
                default -> Optional.empty();
            };
            return valueOpt.orElse(defaultValue);
        } catch (SQLException e) {
            return defaultValue;
        }
    }

Nie dokońca rozumiem komunikatu który dostaję w idei:

Incompatible types. Required Optional<T> but 'ofNullable' was inferred to Optional<T>:
no instance(s) of type variable(s) exist so that String conforms to T
inference variable T has incompatible bounds:
 equality constraints: T
lower bounds: String

Jak można to zrobić? Albo jak można to zrobić lepiej?

0

Kompilator się gubi bo nie wie czy chcesz zwrócić Optional<String> czy Optional<Int>. Czemu w ogóle chcesz wyciągać wartośc z Optionala?

0

Chciałem już w metodzie wyciągnąć sobie wartość żeby potem nie pisać za każdym razem orElse.

1

Trochę zależy od kontekstu, ale zazwyczaj nie chcesz wyjmować zawartości Optionala na zewnątrz (ewentualnie dopiero jak pchasz te dane gdzieś na zewnątrz).

Co do samego pytania, to może strategia da tu radę?

0

Kontekst jest taki. Mam klasy zawierające surowe informacea (nazywam je kodekowe). Używam ich do parsowania z/do jsona a teraz chcę użyć do wzięcia danych z bazy (pola dokładnie pokrywają się z kolumnami w bazie).
Np. taka klasa:

public class PriceCodec extends Codec {
    private final String reservationTemplateId;
    private final String name;
    private final String description;
    private final String currencyCode; // TODO: Zmienić na typ waultowy
    private final int taxRate;
    private final BigDecimal defaultAmountNet;

    public PriceCodec(String id, int numericId, String reservationTemplateId, String name, String description,
                      String currencyCode, int taxRate, BigDecimal defaultAmountNet, LocalDateTime created) {
        super(id, numericId, created);
        this.reservationTemplateId = reservationTemplateId;
        this.name = name;
        this.description = description;
        this.currencyCode = currencyCode;
        this.taxRate = taxRate;
        this.defaultAmountNet = defaultAmountNet;
    }

    public static PriceCodec fromResultSet(ResultSet resultSet) throws SQLException {
        return new PriceCodec(
                resultSet.getString("id"),
                resultSet.getInt("numeric_id"),
                resultSet.getString("reservation_template_id"),
                resultSet.getString("name"),
                resultSet.getString("description"),
                resultSet.getString("currencyCode"),
                resultSet.getInt("tax_rate"),
                resultSet.getBigDecimal("default_amount_net"),
                resultSet.getTimestamp("created").toLocalDateTime()
        );
    }
// ...

Taką koncepcję wymyśliłem ale jeśli masz pomysł że można coś lepiej inaczej to wal :)

9

J bym zrobił to bardziej po ludzku:

@FunctionalInterface
interface ThrowingBiFunction<T, N, R, E extends Exception> {
    R apply(T t, N n) throws E;
}

protected <T> T getValueFromResultSet(ResultSet resultSet, String valueName, T defaultValue, ThrowingBiFunction<ResultSet, String, T, SQLException> extractor) {
        try {
            return Optional.ofNullable(extractor.apply(resultSet, valueName))
                    .orElse(defaultValue);
        } catch (SQLException e) {
            return defaultValue;
        }
    }

I wołasz to przez:

        String a = getValueFromResultSet(rs, "aaa", "test", ResultSet::getString);
        Integer b = getValueFromResultSet(rs, "bbb", 123, ResultSet::getInt);

Żadnych litanii ifów/switchy, żadnych castów, ani cudów.

1 użytkowników online, w tym zalogowanych: 0, gości: 1