1

我正在为 REST-API 实现 PUT 方法。我有一个类似于以下的 POJO:

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

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

在 postgresql 数据库中,brand 表具有以下列:

  • 外部不可见的数据库内部 id (SERIAL)。(这用于连接表)
  • 作为主键的品牌 (TEXT)

我的服务方法如下所示:

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)。我检查了一下,这是由于休眠仍在调用引起的:

insert 
    into
        brand
        (brand) 
    values
        (?)

当 id 为空时,这绝对是我想要的。例如,在创建新品牌时会发生这种情况。但是,当仅覆盖品牌和 id 不为空时,我希望 hibernate 调用它:

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

我知道这可以通过创建自己的保存方法并在紧急情况下覆盖查询来实现。但我很乐观,如果没有这应该是可能的。Bt 我真的找不到合适的答案。我已经在为 postgresql 特定的串行行为找到正确的注释时遇到了问题。

PS:我知道有些人会喊“为什么你会有Brand作为主键而不是id!?” 但这只是数据库的一个简单类/部分。有更复杂的类对内部数据库 id 使用完全相同的方式(并且实际上需要它),但是有多个主键等。所以这对于我的问题来说是一个非常简单的表示。

4

2 回答 2

0

由于 Postgres 使用序列号作为 auto_increment,因此不包括 sql 语句中的 id 插入。在幕后,它为它创建序列。所以你应该为它使用 Generation 类型 IDENTITY。

于 2019-05-20T02:14:42.867 回答
0

如果它是一个字段,@Id您将能够编写一个自定义@GenericGenerator,如果值为空,则获取序列,但由于它不是主键,我认为您最终将不得不拥有一个单独的父实体,它有自己生成的 Id .

于 2020-01-17T12:05:07.253 回答