在Spring Data JPA中,我可以使用@GeneratedValue(strategy = GenerationType.AUTO)
来插入一条带有自定义id的记录,但是对于Spring Data JDBC,如何插入具有自定义id的记录?我已经尝试使用id插入,但是没有抛出异常,并且记录没有插入到表中。
在Spring Data JPA中,我可以使用@GeneratedValue(strategy = GenerationType.AUTO)
来插入一条带有自定义id的记录,但是对于Spring Data JDBC,如何插入具有自定义id的记录?我已经尝试使用id插入,但是没有抛出异常,并且记录没有插入到表中。
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将抛出异常,如果保存了一个聚合并导致更新但更新零行,则此类问题不会被忽略。
// 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);
。
谢谢!
我还在此处添加了一条评论。
我参考了上面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);
}
我也遇到过这个限制。有一些解决方法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-class)。该机制并非特定于SQLite,因此我认为同样的方法也可以适用,尽管需要一些实现。
insert
方法,允许您预填充 id。我想这可能会有所帮助。 - Jens Schauder