Изменить предложение where для пакетного удаления

Я хочу создать пакетное удаление, например: УДАЛИТЬ t ГДЕ t.my_attribute = ?

Первая попытка была:

   private void deleteRecord( ) {
      //loop
      final MyRecord myRecord = new MyRecord();
      myRecord.setMyAttribute(1234);
      getDslContext().batchDelete(myRecord) .execute();
   }

Но здесь SQL всегда содержит pk вместо моего атрибута.

Вторая попытка состояла в том, чтобы создать оператор удаления со значением привязки, но здесь я не нашел решения, как я могу создать предложение where с помощью?

  //loop
  getDslContext().delete( MY_RECORD ).where( ???)
        .bind( 12234 );

Может ли кто-нибудь помочь мне дальше?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
39
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Само утверждение DELETE

Просто добавьте свой предикат сравнения, как в SQL:

getDslContext()
    .delete(T)
    .where(T.MY_ATTRIBUTE.eq(12234))
    .execute();

Предполагается, что вы используете генератор кода, поэтому вы можете статически импортировать ссылку на таблицу com.example.generated.Tables.T.

Пакетирование этого

У вас есть два варианта группирования таких операторов в jOOQ:

1. Использование явного пакетного API

Как объяснено здесь, создайте запрос с фиктивным значением привязки, как показано выше, но не выполняйте его напрямую, вместо этого используйте Batch API:

// Assuming these are your input attributes
List<Integer> attributes = ...

Query query = getDslContext().delete(T).where(T.MY_ATTRIBUTE.eq(0));
getDSLContext()
    .batch(query)
    .bind(attributes
        .stream().map(a -> new Object[] { a }).toArray(Object[][]::new)
    ).execute();

2. Собирать отдельные исполнения в пакетном соединении

Вы всегда можете использовать удобный групповая коллекция в jOOQ, чтобы прозрачно собирать выполняемый SQL и откладывать его в пакет:

getDslContext().batched(c -> {
    for (Integer attribute : attributes)
        c.dsl().getDslContext()
               .delete(T)
               .where(T.MY_ATTRIBUTE.eq(attribute)
               .execute(); // Doesn't execute the query yet
}); // Now the entire batch is executed

В последнем случае строка SQL может генерироваться повторно для каждого отдельного выполнения, поэтому первый вариант, вероятно, лучше подходит для простых пакетов.

Массовое выполнение

Однако зачем выполнять пакет, если можно выполнить один запрос? Просто сделать это, может быть?

getDslContext()
    .delete(T)
    .where(T.MY_ATTRIBUTE.in(attributes))
    .execute();

Да, но тогда у меня нет пакетного удаления, верно? Мне нужно пакетное удаление

MelleD 04.04.2022 12:16

Большое спасибо за подробный ответ. 1. Вот как я это реализовал. Я просто не был уверен, что фиктивное значение было правильным. 2. Посмотрю, может поможет. 3. Я недостаточно знаю JOOQ, но как JOOQ решает проблему, когда в предложении IN слишком много параметров? И действительно ли один запрос с большим предложением «IN» > 1000 элементов быстрее?

MelleD 04.04.2022 16:55

@MelleD: Да, jOOQ решает обе эти проблемы, см. jooq.org/doc/latest/manual/sql-building/dsl-context/…, а также jooq.org/doc/latest/manual/sql-building/dsl-context/…, если вам нужно беспокоиться о конфликте кэша курсора (например, в Oracle). Будет ли это быстрее, вы должны измерить себя, например. используя эта эталонная техника. Вы также можете использовать массивы в некоторых СУБД: blog.jooq.org/….

Lukas Eder 04.04.2022 17:57

@MelleD: имейте в виду, что одним из факторов, который сильно повлияет на производительность, является размер транзакции. Если вы используете базу данных MVCC, удаление 1 млн записей в одной транзакции может создать массу параллелизма в других сеансах, обращающихся к этой таблице. Серебряной пули нет...

Lukas Eder 04.04.2022 18:00

Я использую SQL Server. Так что, если я правильно понял статью, разве ПАКЕТ не должен вызывать меньше проблем?

MelleD 05.04.2022 08:19

@MelleD: я не могу сделать общее заявление о том, какой подход будет для вас лучшим в целом.

Lukas Eder 05.04.2022 08:21

ок надо тестить. Как JOOQ справляется с проблемой параметра 2100 в SQL Server? Разделяются ли выборки, потому что не более 2100 параметров идут напрямую в один выбор "IN"

MelleD 05.04.2022 08:22

@MelleD: Вы проверили ссылки, которые я предоставил? Ответ на это в этом: jooq.org/doc/latest/manual/sql-building/dsl-context/…

Lukas Eder 05.04.2022 10:43

да, конечно «По умолчанию jOOQ автоматически встроит все переменные связывания в любой оператор SQL, как только эти пороговые значения будут достигнуты», и что тогда произойдет? Насколько я знаю, для SQL Server нет никакой разницы, если вы привязываете 2100 '?' или используйте 2100 встроенных значений. Если вы используете более 2100 параметров в IN, вам придется сделать несколько выборок. Или у вас был другой опыт?

MelleD 05.04.2022 12:27

@MelleD: Наши интеграционные тесты говорят об обратном, но почему бы вам просто не попробовать это с jOOQ и посмотреть, что получится. Вы можете включить ведение журнала отладки, чтобы увидеть, что генерирует SQL jOOQ: jooq.org/doc/latest/manual/sql-execution/регистрация

Lukas Eder 05.04.2022 13:03

Ах, я нашел проблему. Я думал, что это автоматически устанавливается из диалекта. Спасибо, хорошая подсказка, тогда мы не справились с этим сами :)

MelleD 05.04.2022 13:42

@MelleD: Да, это часть философии jOOQ. Вам не нужно разбираться со всеми этими скучными низкоуровневыми деталями различных диалектов SQL. :)

Lukas Eder 05.04.2022 14:17

Очень хорошая философия от jOOQ :). Кривая обучения будет продолжать расти, когда мы отойдем от JPA. Я был / я только испорчен весенней загрузкой, что такие диалектные вещи устанавливаются напрямую, но только что протестированные работают отлично. Дополнительные снова узнали, что встроенный идет прямо хорошо знать. Еще раз спасибо Лукасу за очень хороший и подробный ответ.

MelleD 05.04.2022 14:40

Я думаю, что Spring Boot может автоматически настраивать только версию jOOQ с открытым исходным кодом? Как вы думаете, почему кривая обучения повысится?

Lukas Eder 05.04.2022 17:05

Мне все еще нужно протестировать весеннюю загрузку с вариантом без открытого исходного кода. Это вводило в заблуждение, что моя кривая обучения увеличится;)

MelleD 07.04.2022 07:58

Другие вопросы по теме