@Nullable
  public Object valueToDatabase(@Nullable Object value) {
    if (value == null) return null;

    TypeConversion conversion =
        typeConversionRegistry.findConversionToDb(value.getClass()).orElse(null);
    if (conversion != null) return conversion.convert(value);
    else if (value instanceof Enum<?>) return dialect.valueToDatabase(((Enum<?>) value).name());
    else return dialect.valueToDatabase(value);
  }
  /**
   * Returns conversion for converting value of source to target, or returns null if there's no such
   * conversion.
   */
  @NotNull
  private Optional<TypeConversion> findConversionFromDbValue(
      @NotNull Type source, @NotNull Type target) {
    if (isAssignable(target, source)) return Optional.of(TypeConversion.identity());

    Optional<TypeConversion> directConversion =
        typeConversionRegistry.findConversionFromDbValue(source, target);
    if (directConversion.isPresent()) return directConversion;

    Optional<TypeConversion> arrayConversion = findArrayConversion(source, target);
    if (arrayConversion.isPresent()) return arrayConversion;

    Optional<TypeConversion> optionalConversion = findOptionalConversion(source, target);
    if (optionalConversion.isPresent()) return optionalConversion;

    Optional<TypeConversion> enumConversion = findEnumConversion(target);
    if (enumConversion.isPresent()) return enumConversion;

    return Optional.empty();
  }