Скажите Hibernate, чтобы база данных генерировала значение, только когда оно пустое - PullRequest
0 голосов
/ 19 мая 2019

Я реализую методы PUT для REST-API. У меня есть POJO, похожее на следующее:

public class Brand implements Serializable {
    @Column(columnDefinition = "serial")
    @Generated(GenerationTime.INSERT)
    @JsonIgnore
    private Integer id;

    @Id
    @JsonProperty("brand")
    private String brand;
    .
    .
    .
}

В базе данных postgresql таблица брендов имеет следующие столбцы:

  • внутренний идентификатор базы данных (SERIAL), который не должен быть виден снаружи (используется для объединения таблиц)
  • бренд (ТЕКСТ), который является первичным ключом

Мой метод Service выглядит следующим образом:

public Brand updateBrand(String brand, Brand update) {
    Brand b = brandRepository.findBrandByBrand(brand);
    if(b == null) { //If not exists create new one
        b = new Brand(null, brand);
    }
    else {  //If exists keep id, delete old one and create new entry
        if(update != null && update.getBrand() != null) {
            brandRepository.delete(b);
        }
        ServiceUtils.copyProperties(update, b); //This is within the if clause, because brand is the only value
    }
    return brandRepository.save(b);
}

И контроллер будет выглядеть примерно так:

@PutMapping(value = "/brand/{brand}")
public ResponseEntity<Brand> updateBrand(@PathVariable("brand") String brand,
                                         @RequestBody Brand update) {
    Brand updated = articleNumberService.updateBrand(brand, update);
    if(updated == null) {
        throw new EntryCreationFailedException(brand); //self made exception
    }
    return new ResponseEntity<>(updated, HttpStatus.OK);
}

Теперь моя следующая проблема заключается в том, что при вызове PUT ../brand/stackoverflow с телом:

{"brand":"StackOverflow")

удаляет старую марку stackoverflow (например, с id = 1) и создает новую с именем StackOverflow. Но при проверке базы данных столбец id увеличивается (поэтому теперь он имеет id = 2). Я проверил, и это вызвано тем, что Hibernate все еще вызывает:

insert 
    into
        brand
        (brand) 
    values
        (?)

Это определенно то, что я хочу, когда id равен нулю. Что происходит, например, при создании нового бренда. Но когда только переопределение бренда и id не равно нулю, я хочу, чтобы hibernate назвал это:

insert 
    into
        brand
        (id, brand) 
    values
        (?, ?)

Я знаю, что это было бы возможно, если создать собственный метод сохранения и в экстренном случае переопределить запрос. НО я довольно оптимистичен, что это возможно без. Но я не могу найти подходящих ответов на это. У меня уже были проблемы с поиском правильных аннотаций для последовательного поведения, специфичного для postgresql.

П.С .: Я знаю, что некоторые будут кричать "почему вы выбрали Бренд в качестве первичного ключа, а не идентификатор !?" Но это только простой класс / часть базы данных. Существуют более сложные классы, которые используют точно такой же способ для внутреннего идентификатора базы данных (и действительно нуждаются в нем), но имеют несколько первичных ключей и т. Д. Так что это довольно простое представление для моей проблемы.

1 Ответ

0 голосов
/ 20 мая 2019

Поскольку Postgres использует серийный номер в качестве auto_increment, он не включает вставку идентификатора в оператор sql.За сценой создается последовательность для него.Таким образом, вы должны использовать для этого тип поколения IDENTITY.

...