我正在写一个Vaadin应用程序,我遇到了网格选择的问题。如果我先编辑一个项目,然后删除它,我会得到一个例外。
org.springframework.orm.jpa.JpaObjectRetrievalFailureException:无法找到ID为252的com.mmm.inventur.data.StockAtLocation;嵌套异常是javax.persistence.EntityNotFoundException:无法找到id为252的com.mmm.inventur.data.StockAtLocation 在org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:389)〜[spring-orm-4.3.13.RELEASE.jar:4.3.13.RELEASE] 在......
如果我首先取消选择该项目并将其删除,则一切正常。
我编辑的项目是Article的实例,它包含多个StockAtLocation对象,通过编辑Article实例,我从集合中删除了StockAtLocation以及Article对象。
ibm-web-ext.xml
抛出异常
@Entity
@Getter
@Setter
public class Article implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(nullable = false, unique = true)
private Long id;
@Column(nullable = true, unique = true)
private Long carlaId;
@Column(nullable = true, unique = true)
private Long ean;
@Column(nullable = false, unique = false)
private String name;
private String descr;
@Column(nullable = false)
@OneToMany(mappedBy = "article", cascade = CascadeType.ALL)
private List<StockAtLocation> stocks;
public Article() {
stocks = new ArrayList<>();
}
public int getCompleteCntStock() {
int re = 0;
for (StockAtLocation stock : stocks) {
re += stock.getCntStock();
}
return re;
}
public int getCompleteOldStock() {
int re = 0;
for (StockAtLocation stock : stocks) {
re += stock.getOldStock();
}
return re;
}
}
@Entity
@Getter
@Setter
public class StockAtLocation implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(nullable = false, unique = true)
private Long id;
private String stockArea;
private Timestamp lastModify;
private String note;
private int oldStock;
private int cntStock;
@ManyToOne(cascade = CascadeType.PERSIST, optional = true)
private Device modifiedBy;
@JoinColumn(nullable = false)
@ManyToOne(optional = false, cascade = CascadeType.PERSIST)
private StorageLocation storageLocation;
@ManyToOne
private Article article;
}
删除条款操作
@Service
public class ArticleService {
@Autowired
private ArticleRepository articleRepo;
public void save(final Article article) {
this.articleRepo.save(article);
}
@Transactional
public void deleteArticle(final Article delete) {
try {
this.articleRepo.delete(delete);
} catch (JpaObjectRetrievalFailureException e) {
// right here the exception occurs
throw e;
}
}
删除StockAtLocation操作
this.btnDelete.addClickListener(new Button.ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
for (Article selectedItem : articleGrid.getSelectedItems()) {
arService.deleteArticle(selectedItem);
}
dataProvider.refreshAll();
articleGrid.deselectAll();
}
});
modifyCallBack
private Article modified;
@Override
public void buttonClick(Button.ClickEvent event) {
// store changes in the database
Set<StockAtLocation> selectedItems = stockGrid.getSelectedItems();
stockGrid.deselectAll();
modifyCallBack.deleteStocks(modified, selectedItems);
// update the grid
stockGrid.setItems(modified.getStocks());
}
完整堆栈跟踪:
(deleteFrom, delete) -> {
if (deleteFrom.getStocks().isEmpty()) {
return;
} else if (!deleteFrom.getStocks().removeAll(delete)) {
throw new Error("removing does not work!");
}
stockService.delete(delete);
dataProvider.refreshItem(deleteFrom);
});
答案 0 :(得分:0)
我的猜测是,当您更新项目时(即在编辑完成后),数据库中的版本会更新,但内存中的实体仍然具有旧版本,当您尝试删除旧项目时版本,你得到例外,因为没有找到该版本。当您尝试直接在UI中使用数据库实体时,这是一个非常常见的问题。
有几种方法。另一种方法是在更新后重新获取项目,以便内存版本与数据库中的版本相同。其他方式是使用中间层和DTO。在具有更复杂业务逻辑的应用程序中,DTO是必需的。