LINUX.ORG.RU

Однажды установленное jsonb поле не удается изменить

 , , , ,


0

1

Имеется вебприложение на следующем стеке: backend: java 8, spring-boot, spring-mvc, hibernate, postgresql. frontend: reactjs, material-ui.

Возникла необходимость отображать яндекс-карту с метками. Я решил сохранять информацию, которую получаю от яндексовского сервиса в jsonb.

Сущность в которой необходимо сохранять инфу:

@NoArgsConstructor
@Getter @Setter
@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true)
@Entity
public class Location extends Identifiable implements Serializable {
    @Type(type = "jsonb")
    @Column(columnDefinition = "jsonb")
    private Geolocation geolocation;
}
https://pastebin.com/FX9XUxjg

Классы, являющиеся отражением структуры json:

@NoArgsConstructor
@Getter @Setter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@TypeDefs({
        @TypeDef(name = "json", typeClass = JsonStringType.class),
        @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
@MappedSuperclass
public class Geolocation {
    private Double latitude;
    private Double longitude;
    private Address address;
}
https://pastebin.com/dqDTeddD

@NoArgsConstructor
@Getter
@Setter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@TypeDefs({
        @TypeDef(name = "json", typeClass = JsonStringType.class),
        @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
@MappedSuperclass
public class Address {
    private String countryCode;
    private String formatted;
    private String postalCode;
    private Map<String,String> components = new HashMap<>();
}

https://pastebin.com/3pVBBGGH

Метод контроллера, вызывающийся для сохранения геолокации:

@Log4j2
@Controller
@RequestMapping(value = "/api/locations")
public class LocationController {

    @Autowired
    private ModelMapper modelMapper;

    @Autowired
    private LocationRepository locationRepository;

    @PreAuthorize("hasRole('ADMIN')")
    @Transactional
    @RequestMapping(value = "/{id}/geolocation", method = RequestMethod.POST)
    @ResponseBody
    public com.helan.videoafisha.dto.general.Location saveGeolocation(
            @PathVariable("id") Long id,
            @RequestBody com.helan.videoafisha.dto.backend.frontend.reactjs.locations.with_geolocation.Geolocation modelGeolocation) {
        Location location = locationRepository.getOne(id);
        Geolocation geolocation = modelMapper.map(modelGeolocation, Geolocation.class);
        location.setGeolocation(geolocation);
        locationRepository.save(location);
        return modelMapper.map(location, com.helan.videoafisha.dto.general.Location.class);
    }
}
https://pastebin.com/BbxWxpNH

Суть проблемы заключается в том, что когда geolocation равен null, тогда даный метод отрабатывает корректно: https://imgur.com/PE5lvKQ.png

Hibernate: 
    update
        backend.location 
    set
        geolocation=?,
        max_device_count=?,
        site_id=?,
        time_zone_id=?,
        title=? 
    where
        id=?
2020-04-01 16:42:31.339 DEBUG - c.h.v.b.m.l.LogRequestFilter             : 200 POST /api/locations/1/geolocation [member #1/admin@mail.ru] 127.0.0.1:41090 {"isRequesting":false,"latitude":55.69962195079022,"longitude":37.62218505859374,"address":{"countryCode":"RU","formatted":"Россия, Москва, Варшавское шоссе, 13с4","postalCode":"117105","components":{"country":"Россия","province":"Центральный федеральный округ","locality":"Москва","street":"Варшавское шоссе","house":"13с4"}}}
https://imgur.com/8mc7odJ.png

После этого, когда geolocation не null повторные вызовы с другими данными не приводят ни к каким изменениям. Даже update не вызывается. Отладка метода не выявила никаких иных условий выполнения.

2020-04-01 16:49:14.836 DEBUG - c.h.v.b.m.l.LogRequestFilter             : 200 POST /api/locations/1/geolocation [member #1/admin@mail.ru] 127.0.0.1:41202 {"isRequesting":false,"latitude":55.70117301801526,"longitude":37.58991271972656,"address":{"countryCode":"RU","formatted":"Россия, Москва, улица Вавилова, 9Ас17","postalCode":"117312","components":{"country":"Россия","province":"Центральный федеральный округ","locality":"Москва","street":"улица Вавилова","house":"9Ас17"}}}

Чем может быть вызвано подобное поведение? Если вручную установить колонку geolocation в null, то метод отработает как надо.

Возможно неправильно работает equals(). Кажется ломбок его наполовину только нагенерил, но сравнения по полям нет и поэтому он гонит постоянно true.

spoilt ★★★ ()
Ответ на: комментарий от spoilt

Ай да ты, а да молодец. Совершенно ускорльзнула от моего внимания опция аннотации @EqualsAndHashCode onlyExplicitlyIncluded. Спасибо! Всё задаботало!

popov-aa ()
Последнее исправление: popov-aa (всего исправлений: 1)