Vaadin网格错误的选择

时间:2018-04-12 08:38:00

标签: spring hibernate vaadin8

我正在写一个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);
 });

1 个答案:

答案 0 :(得分:0)

我的猜测是,当您更新项目时(即在编辑完成后),数据库中的版本会更新,但内存中的实体仍然具有旧版本,当您尝试删除旧项目时版本,你得到例外,因为没有找到该版本。当您尝试直接在UI中使用数据库实体时,这是一个非常常见的问题。

有几种方法。另一种方法是在更新后重新获取项目,以便内存版本与数据库中的版本相同。其他方式是使用中间层和DTO。在具有更复杂业务逻辑的应用程序中,DTO是必需的。