Как использовать оператор IN в сочетании с JDBI?

Добрый день.

Я пытаюсь связать список со строками с запросом, который использует оператор IN. im использовать Oracle. Я сделал это по примеру, описанному в ссылке: Как использовать оператор IN с JDBI?

List<String> ms = new ArrayList();
    ms.add("Novosibirsk");
    ms.add("Perm");

public interface CityDAO {
   @RegisterMapper(CitiesMapper.class)
   @SqlQuery("SELECT *
              FROM Universities
              WHERE Location IN (:cities)")
   List<cities> getItems(@Bind("cities") List<String> cities);}
 }

Я создал ListArgumentFactory

public class ListArgumentFactory implements ArgumentFactory<List> {
    @Override
    public boolean accepts(Class<?> expectedType, Object value, StatementContext ctx) {
    return value instanceof List;
    }

   @Override
   public Argument build(Class<?> expectedType, final List value, StatementContext ctx) {
    return new Argument() {
        @Override
        public void apply(int position, PreparedStatement statement, StatementContext ctx) throws SQLException {
            String type = null;
            if(value.get(0).getClass() == String.class){
                type = "varchar";
            } else if(value.get(0).getClass() == Integer.class){
                // For integer and so on...
            } else {
                // throw error.. type not handled
            }
            Array array = ctx.getConnection().createArrayOf(type, value.toArray());
            statement.setArray(position, array);
        }
    };
  }
 }

Я зарегистрировал завод

   public class DBI extends AbstractModule {
     private DBI dbi;

     @Override
     protected void configure() {
       this.dbi = new DBI(provideConfig().url());
       this.dbi.registerArgumentFactory(new ListArgumentFactory());
    }
  }

Но когда я делаю запрос, я получаю исключение

org.skife.jdbi.v2.exceptions.UnableToCreateStatementException: Exception while binding 'cities' [statement:"SELECT * FROM Universities WHERE Location IN (:cities)", arguments:{ positional:{}, named {cities:factory.ListArgumentFactory$1@6788168c}, finder:[]}]

Помогите мне понять, что я делаю неправильно

java,oracle11g,jdbi,

0

Ответов: 1


0

Согласно документации JDBI , достижение чего-то подобного с использованием Oracle может быть довольно сложным, поэтому лучше было бы использовать описанный первый подход (UseStringTemplate3StatementLocator):

Oracle поддерживает нечто подобное, но вам нужно использовать специальные API-интерфейсы Oracle и экземпляры oracle.sql.ARRAY. В случае Oracle вы должны предварительно объявить тип массива в базе данных в первую очередь, и поскольку он хранит массив в базе данных, освободите его после вызова.

Сказав это, существует простой подход, который можно использовать для выполнения этой работы в Oracle, которая должна присоединиться к элементам в списке с запятой. Я изменил ListArgumentFactory с помощью метода Java 8 String.join:

public class ListArgumentFactory implements ArgumentFactory<List> {

    @Override
    public boolean accepts(Class<?> expectedType, Object value, StatementContext ctx) {
        return value instanceof List;
    }

    @Override
    public Argument build(Class<?> expectedType, final List value, StatementContext ctx) {
        return new Argument() {
            @Override
            public void apply(int position, PreparedStatement statement, StatementContext ctx) throws SQLException {
                statement.setString(position, String.join(",", value));
            }
        };
    }
}

Я пробовал подход, описанный в документации JDBI, для использования oracle.sql.ARRAY и пользовательского TYPE в Oracle DB, но для меня это не удавалось.

Java, oracle11g, jdbi,
Похожие вопросы
Яндекс.Метрика