如何使用Spring data jdbc插入具有自定义id的记录?

问题描述 投票:0回答:4

对于 Spring Data JPA,我可以使用

@GeneratedValue(strategy = GenerationType.AUTO)
插入具有自定义 id 的记录,但是对于 Spring Data JDBC,如何插入具有自定义 id 的记录?我尝试用id插入,但没有抛出异常,并且记录没有插入到表中。

java spring insert id-generation spring-data-jdbc
4个回答
19
投票

使用 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());
            }
        }
    };
}

Spring Data Examples

中有一个示例演示了这一点

您的行没有插入表中,但也没有收到异常的原因是:Spring Data JDBC 得出结论,自设置 ID 并执行更新以来该实体已经存在。 但由于它不存在,更新无法更新任何行,因此什么也没有发生。 可能值得创建一个改进请求来检查更新计数是否为 0。

更新

自版本 1.1 起,

JdbcAggregateTemplate.insert
可用,允许您执行插入操作,而无需检查聚合是否是新的。 如果需要,您可以使用它在存储库中创建自定义方法,或者您可以在需要的地方自动装配模板并直接使用它。

对于 DATAJDBC-438,如果保存聚合,Spring Data JDBC 将引发异常,从而导致更新,但更新会更新零行,因此这种问题不会被忽视。

进一步更新

有一篇博客文章详细介绍了 Spring Data JDBC 中生成 id 值的各种方法


5
投票

我找到了另一种方法来解决这个问题,虽然有点麻烦。

// 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);

插入时需要添加一行

user.setNew(true);
.

谢谢!

我还添加了评论这里


0
投票

我参考了Xianghi上面的答案,使用方式略有不同:

@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);
}

0
投票

我也在与限制作斗争。有一些解决方法https://spring.io/blog/2021/09/09/spring-data-jdbc-how-to-use-custom-id- Generation,但它们对我来说并不是完美的解决方案。

我正在为 SQLite 开发 Spring Data JDBC 集成,它提供了一个存储库帮助程序类,该类公开 JdbcAggregateTemplate 的

insert()
update()
API (https://github.com/komamitsu/spring-data-sqlite#repository-helper -类)。该机制不是 SQLite 特定的,因此我认为尽管需要一些实现,但同样的方式也可以工作。

© www.soinside.com 2019 - 2024. All rights reserved.