对于 Spring Data JPA,我可以使用
@GeneratedValue(strategy = GenerationType.AUTO)
插入具有自定义 id 的记录,但是对于 Spring Data JDBC,如何插入具有自定义 id 的记录?我尝试用id插入,但没有抛出异常,并且记录没有插入到表中。
使用 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 JDBC 得出结论,自设置 ID 并执行更新以来该实体已经存在。 但由于它不存在,更新无法更新任何行,因此什么也没有发生。 可能值得创建一个改进请求来检查更新计数是否为 0。
更新
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 -类)。该机制不是 SQLite 特定的,因此我认为尽管需要一些实现,但同样的方式也可以工作。