Пакетная вставка/обновление MyBatis для Oracle
Недавно я начал изучать использование myBatis. Теперь я сталкиваюсь с таким сценарием, мне нужно постоянно извлекать новый список объектов через WebService, а затем для этого списка мне нужно вставить/обновить каждый объект в оракуле Таблица DB через myBatis.
Сложная часть заключается в том, что я не могу просто выполнять пакетную вставку каждый раз, потому что некоторые из объектов могут уже существовать в БД, для этих записей мне нужно обновить поля из них вместо новой вставки.
Мое текущее решение может быть очень глупо, с использованием Java, построить список объектов из webservice, пропустить через каждый из них, сделать выбор myBatis, если он не является нулевым (уже существует в db), затем выполните обновление myBatis; в противном случае сделайте вкладку myBatis для этого нового объекта.
Достигнута функция. Но мой технический руководитель говорит, что он очень низкоэффективен, поскольку выполнение цикла for с использованием Java и вставка/обновление по одному потребует много системного ресурса. Он посоветовал мне делать пакетную вставку с помощью myBatis, передав список объектов.
Пакетная вставка в myBatis проста, однако, поскольку я не просто вставляю (для существующих записей мне нужно сделать обновление), я не думаю, что пакетная вставка здесь подходит. Я задумался об этом за некоторое время и понял, что мне нужно будет использовать "merge" вместо "insert" (для Oracle).
Примеры, которые я искал для слияния в myBatis, относятся только к одному объекту, а не к пакету. Таким образом, я хочу выяснить, могут ли эксперты предложить мне несколько примеров того, как выполнить пакетное слияние в MyBatis (правильный способ написать Mapper)?
Ответы
Ответ 1
В моем случае также есть такой же сценарий. Я использовал для цикла, чтобы проверить, существует ли эта запись в базе данных или нет, а затем в соответствии с этим я добавил этот объект в два массива для вставки или обновления. А затем использовал пакет для вставки и обновления после цикла для этого списка.
здесь бывший для обновления в соответствии с другим, где условие
1] это для обновления
<foreach collection="attendingUsrList" item="model" separator=";">
UPDATE parties SET attending_user_count = #{model.attending_count}
WHERE fb_party_id = #{model.eid}
</foreach>
2] это для вставки
<insert id="insertAccountabilityUsers" parameterType="AccountabilityUsersModel" useGeneratedKeys="false">
INSERT INTO accountability_users
(
accountability_user_id, accountability_id, to_username,
record_status, created_by, created_at, updated_by, updated_at
)
VALUES
<foreach collection="usersList" item="model" separator=",">
(
#{model.accountabilityUserId}, #{model.accountabilityId}, #{model.toUsername},
'A', #{model.createdBy}, #{model.createdAt}, #{model.updatedBy}, #{model.updatedAt}
)
</foreach>
</insert>
В методе дао объявить как
void insertAccountabilityUsers(@Param("usersList") List<AccountabilityUsersModel> usersList);
Обновить
Вот мой код сеанса
public static synchronized SqlSession getSqlBatchSession() {
ConnectionBuilderAction connection = new ConnectionBuilderAction();
sf = connection.getConnection();
SqlSession session = sf.openSession(ExecutorType.BATCH);
return session;
}
SqlSession session = ConnectionBuilderAction.getSqlSession();
На самом деле я уже дал полный пример здесь по этому вопросу
Ответ 2
Принятый ответ не является рекомендуемым способом обработки пакетных операций. Он не показывает истинные пакетные инструкции, так как режим запуска партии должен использоваться при открытии сеанса. См. Этот пост, в котором разработчик кода рекомендовал, чтобы надлежащий способ пакетного обновления (или вставки) состоял в том, чтобы открыть сеанс в пакетном режиме и повторно вызвать обновление (или вставить) для одной записи.
Вот что работает для меня:
public void updateRecords(final List<GisObject> objectsToUpdate) {
final SqlSession sqlSession = MyBatisUtils.getSqlSessionFactory().openSession(ExecutorType.BATCH);
try {
final GisObjectMapper mapper = sqlSession.getMapper(GisObjectMapper.class);
for (final GisObject gisObject : objectsToUpdate) {
mapper.updateRecord(gisObject);
}
sqlSession.commit();
} finally {
sqlSession.close();
}
}
Не используйте foreach в своем обновлении/вставке и убедитесь, что он только обновляет/вставляет одну запись. Я столкнулся с неразрешимыми ошибками оракула, выполнив это в соответствии с принятым ответом (недопустимый символ, оператор не закончился и т.д.). Как указывает связанная почта, обновление (или вставка), показанное в принятом ответе, на самом деле является просто гигантским выражением sql.