Spring Mongo обновляется только ненулевыми полями нового POJO

Модель пользователя:

@Document(collection = "USER")
public class UserModel {
    private String id;
    private String username;
    @Indexed(unique = true)
    private String email;
    private String password;
    private String firstName;
    private String lastName;
}

Пользовательский репозиторий:

@Repository
public interface UserRepository extends MongoRepository<UserModel, String> {

    Optional<UserModel> findByEmail(String email);
    Optional<UserModel> findByUsername(String username);
}

Сохранение пользовательского документа следующим образом:

@Autowired
UserRepository userRepo;

public someMethod() {
    UserModel user = new UserModel();
    //Set all fields....
    userRepo.save(user);
}

Попытка обновления следующим образом:

@Autowired
UserRepository userRepo;

public someMethod() {
    UserModel user = new UserModel();
    user.setId("A valid Id got from database by last insert")
    user.setFirstName("New first name");
    // Remaining fields are null now
    userRepo.save(user);
}

Здесь нулевые значения будут вставлены MongoRepository.

Есть ли какие-либо настройки, с помощью которых я могу указать MongoRepository избегать нулевых значений при обновлении?

Если мы сделаем это методом MongoTemplate updateFirst(), нам нужно будет добавить if условий для всех полей POJO. Какое лучшее решение в этом случае?


person iamcrypticcoder    schedule 06.06.2020    source источник
comment
Отвечает ли это на ваш вопрос? Spring Data MongoDB - игнорировать пустые объекты   -  person Valijon    schedule 06.06.2020


Ответы (1)


Попробуйте сначала получить из базы данных пользователя, затем обновить свои данные и сохранить в базе данных.

UserModel user = userRepo.findById(id); // Fetch from database
user.setFirstName("New first name");    // Update the data
userRepo.save(user);                    // Save in the database

Или используйте пользовательский запрос для обновления только выбранных полей. Здесь, чтобы сделать его динамичным, создайте Map<String, Object> из UserModel и удалите нулевое значение.

ObjectMapper oMapper = new ObjectMapper();
Map<String, Object> dataMap = oMapper.convertValue(user, Map.class);
map.values().removeIf(Objects::isNull);

А теперь установите карту в Update, затем обновите в базе данных.

Update update = new Update();
dataMap.forEach(update::set);
Query query = new Query().addCriteria(where("_id").is(id));
mongoTemplate.update(UserModel.class).matching(query).apply(update).first();
person Eklavya    schedule 06.06.2020
comment
Это требует дополнительного запроса. Наша цель — выполнить один запрос на обновление с меньшим количеством кода. - person iamcrypticcoder; 06.06.2020
comment
Вы использовали Jackson ObjectMapper. Правильно? Что ж, сделать JSON как-то — хорошая идея. Давайте посмотрим, есть ли другой хороший способ сделать это. - person iamcrypticcoder; 07.06.2020
comment
@iamcrypticcoder Да. Если ваши обновленные узлы являются динамическими, то я думаю, что это хороший способ. Или, если они исправлены, просто добавьте Update — это хороший способ. - person Eklavya; 07.06.2020
comment
@Eklvya У меня есть мнение об этом преобразовании JSON. В принципе, я имел это в виду. Разве это преобразование не требует времени? Кроме того, Джексон плохо работает с небольшой полезной нагрузкой по сравнению с GSON. Я имею в виду время, необходимое Джексону. - person iamcrypticcoder; 07.06.2020
comment
@iamcrypticcoder Зависит от того, используете ли вы синглтон (создаете bean-компонент), тогда это не займет слишком много времени. Если вы создаете Map‹String, Object› вручную, то этого можно избежать. - person Eklavya; 07.06.2020
comment
@Eklvyam Будет ли это работать, когда POJO вложены. Например, встроенный документ основного документа. Я пытаюсь найти решение, которое будет работать для следующей структуры объектов. - person iamcrypticcoder; 09.06.2020
comment
Должно работать так же, как вы используете Map<String, Object>, но вы должны делать то же самое и для вложенного объекта. - person Eklavya; 09.06.2020