简体   繁体   English

如何插入自定义ID使用Spring数据jdbc的记录?

[英]How to insert a record with custom id use Spring data jdbc?

For Spring Data JPA, I can use @GeneratedValue(strategy = GenerationType.AUTO) to insert a record with a custom id, but for Spring Data JDBC, how do I insert a record with custom id?对于Spring 数据JPA,我可以使用@GeneratedValue(strategy = GenerationType.AUTO)插入一条带有自定义id 的记录,但是对于Spring 数据JDBC,我如何插入一条带有自定义id 的记录? I hav tried to insert with id, but no exception was thrown and the record was not inserted into the table.我试图用 id 插入,但没有抛出异常,记录也没有插入到表中。

The way to do that with Spring Data JDBC is to register a BeforeSaveEvent ApplicationListener that creates the id and sets it in the entity.使用 Spring Data JDBC 做到这一点的方法是注册一个BeforeSaveEvent ApplicationListener来创建 id 并将其设置在实体中。

@Bean
public ApplicationListener<BeforeSaveEvent> idSetting() {

    return event -> {

        if (event.getEntity() instanceof LegoSet) {

            LegoSet legoSet = (LegoSet) event.getEntity();
            if (legoSet.getId() == null) {
                legoSet.setId(createNewId());
            }
        }
    };
}

There is an example demonstrating that in the Spring Data ExamplesSpring Data Examples 中有一个例子证明了这一点

The reason your row wasn't inserted in the table, but you also didn't get an exception is: Spring Data JDBC concluded that the entity already existed since the ID was set and performed an update.您的行未插入表中但您也没有收到异常的原因是:Spring Data JDBC 得出结论,自设置 ID 并执行更新以来实体已经存在。 But since it didn't exist the update failed to update any rows, so nothing happened.但由于它不存在,更新未能更新任何行,所以什么也没发生。 It might be worth creating an improvement request to check the update count against 0.创建改进请求以检查更新计数是否为 0 可能是值得的。

UPDATE更新

Since version 1.1 JdbcAggregateTemplate.insert is available allowing you do an insert without any check if an aggregate is new.由于版本 1.1 JdbcAggregateTemplate.insert可用,允许您在不检查聚合是否为新的情况下进行插入。 You can use that to create a custom method in your repository, if you want, or you can autowire the template wherever you need it and use it directly.如果需要,您可以使用它在存储库中创建自定义方法,或者您可以在任何需要的地方自动装配模板并直接使用它。

Also with DATAJDBC-438 Spring Data JDBC will throw an exception if an aggregate is saved, resulting in an update but the update updates zero rows so this kind of problem doesn't get unnoticed.同样使用 DATAJDBC-438 Spring Data JDBC 会在保存聚合时抛出异常,导致更新但更新更新零行,因此此类问题不会被忽视。

I found another way to solve this problem although it's a little trouble.我找到了另一种方法来解决这个问题,虽然有点麻烦。

// BaseEntity
public class BaseEntity implements Persistable, Serializable {

    @Id
    String id;

    @Transient
    @JsonIgnore
    private boolean newEntity;

    @Override
    public Object getId() {
        return id;
    }

    public void setNew(boolean newInstance) {
        this.newEntity = newInstance;
    }

    @Override
    @JsonIgnore
    public boolean isNew() {
        return newEntity;
    }
}

// User
User extends BaseEntity
...


// insert
User user = new User();
user.id = "5bffb39cc5e30ba067e86dff";
user.setName("xiangzi");
user.setNew(true);
userRepository.save(user);


// update
User user = new User();
user.id = "5bffb39cc5e30ba067e86dff";
user.setName("xiangzi2");
userRepository.save(user);

When insert needs to add the line user.setNew(true);插入时需要添加一行user.setNew(true); . .

Thanks!谢谢!

I also added a comment here .我还在这里添加了评论。

I referred to Xianghi's answer above and used it slightly differently:我在上面提到了翔希的回答,并略有不同:

@Data
@Table
public class TestDataTable implements Persistable<String> {


@Id
String id;

private String name;

@Transient
@JsonIgnore
private boolean newEntity;

@Override
public String getId() {
    return id;
}

public void setNew(boolean newInstance) {
    this.newEntity = newInstance;
}

@Override
@JsonIgnore
public boolean isNew() {
    return newEntity;
}
}

// created new record when we use task.setNew(true) in TestDataTable with String Id.
public Mono<TestDataTable> saveTestData(TestDataTable task) {
    task.setNew(true);

    return testRepository.save(task);
}

I also struggled with the limitation.我也为限制而苦苦挣扎。 There are some workarounds https://spring.io/blog/2021/09/09/spring-data-jdbc-how-to-use-custom-id-generation , but they're not perfect solutions for me.有一些解决方法https://spring.io/blog/2021/09/09/spring-data-jdbc-how-to-use-custom-id-generation ,但它们对我来说不是完美的解决方案。

I'm developing Spring Data JDBC integration for SQLite and it provides a repository helper class that exposes JdbcAggregateTemplate's insert() and update() APIs ( https://github.com/komamitsu/spring-data-sqlite#repository-helper-class ).我正在为 SQLite 开发 Spring 数据 JDBC 集成,它提供了一个存储库助手 class,它公开了 JdbcAggregateTemplate 的insert()update() API( https://github.com/komamitsu/spring-data-sqlhelper ). The mechanism isn't SQLite specific, so I think the same way would work although some implementation will be needed.该机制不是特定于 SQLite 的,因此我认为尽管需要一些实现,但同样的方法也可以工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM