使用Vaadin Crud组件时列轴未正确排序如何解决
问题原因
你遇到的排序异常主要由以下两个常见原因导致:
- 调用
crud.getGrid().setSortableColumns()的时机和参数错误:无参的setSortableColumns()会将当前Grid中所有已存在的列全部设为可排序,但你是在Crud自动生成列之后才移除password列,且没有显式指定需要支持排序的列键,容易出现列排序属性绑定错乱的问题。 - 自定义
UserDataProvider未正确处理排序逻辑:如果你的UserDataProvider是继承自后端数据Provider(而非内存ListDataProvider),没有重写逻辑处理Grid传来的排序参数,就会导致排序规则无法传递到数据查询层,返回的数据顺序和前端点击的排序规则不匹配。
异常效果参考:
正确实现步骤
1. 调整列操作的顺序,显式指定可排序列
调整列操作的先后顺序,移除不需要的列之后,再显式传入需要支持排序的列的键名,不要用无参方法:
Crud<OpvUser> crud = new Crud<>(OpvUser.class, createUserEditor()); crud.getGrid().addItemDoubleClickListener(e -> crud.edit(e.getItem(), Crud.EditMode.EXISTING_ITEM)); // 先调整列配置 crud.getGrid().removeColumnByKey("password"); // 显式指定要支持排序的列,替换为你实际的业务列键 crud.getGrid().setSortableColumns("id", "username", "phone", "createTime"); UserDataProvider dataProvider = new UserDataProvider(); crud.setDataProvider(dataProvider); dataProvider.refreshAll(); crud.addThemeVariants(CrudVariant.NO_BORDER); add(crud);
2. 补全UserDataProvider的排序逻辑
如果是自定义后端数据Provider,需要在查询方法中获取前端传来的排序参数,传递到数据查询层,以下是JPA场景的示例写法,可根据你使用的持久层框架调整:
public class UserDataProvider extends AbstractBackEndDataProvider<OpvUser, String> { @Override protected Stream<OpvUser> fetchFromBackEnd(Query<OpvUser, String> query) { // 获取前端传递的排序规则 List<QuerySortOrder> sortOrders = query.getSortOrders(); Sort sort = Sort.unsorted(); for (QuerySortOrder order : sortOrders) { sort = sort.and( order.getDirection() == SortDirection.ASCENDING ? Sort.by(order.getSorted()).ascending() : Sort.by(order.getSorted()).descending() ); } // 携带排序条件查询数据 return userRepository.findAll(sort).stream(); } @Override protected int sizeInBackEnd(Query<OpvUser, String> query) { return userRepository.count(); } }
3. 小数据量兜底方案
如果你的业务数据量很小,可直接使用Vaadin自带的内存ListDataProvider,无需自行实现排序逻辑,框架会自动处理排序操作:
// 直接从数据库查全量数据交给内存Provider处理 ListDataProvider<OpvUser> dataProvider = DataProvider.ofCollection(userRepository.findAll()); crud.setDataProvider(dataProvider);
内容的提问来源于stack exchange,提问作者Sayer Arab
相关产品推荐
相关产品推荐

