Java 限制Vaadin表中选定行的数量

Java 限制Vaadin表中选定行的数量,java,vaadin,Java,Vaadin,在我们的一个应用程序中,我们使用惰性查询容器来浏览可能非常大的数据集。这很有效。但是,在使用多选表时,可以选择任意数量的行。 在我们的例子中,这可能导致选择多达500.000行(Vaadin限制),然后使VM崩溃 有没有办法限制所选行的数量 下面是一个显示问题的示例: public class UIImpl extends UI { private int SIZE = 500000; @Override protected void init(VaadinReques

在我们的一个应用程序中,我们使用惰性查询容器来浏览可能非常大的数据集。这很有效。但是,在使用多选表时,可以选择任意数量的行。 在我们的例子中,这可能导致选择多达500.000行(Vaadin限制),然后使VM崩溃

有没有办法限制所选行的数量

下面是一个显示问题的示例:

public class UIImpl extends UI {
    private int SIZE = 500000;

    @Override
    protected void init(VaadinRequest request) {

        // add a large table
        LazyQueryContainer lqc = new LazyQueryContainer(
            new QueryFactory() {
                public Query constructQuery(QueryDefinition qd) {
                    return new Query() {
                        @Override
                        public int size() {
                            return SIZE;
                        }

                        @Override
                        public void saveItems(List<Item> addedItems, List<Item> modifiedItems, List<Item> removedItems) {   }

                        @Override
                        public List<Item> loadItems(int startIndex, int  count) {
                            List<Item> r = new ArrayList<>(count);
                            for (int i = startIndex; i<startIndex+count;i++) {
                                PropertysetItem item = new PropertysetItem();
                                item.addItemProperty("name", new ObjectProperty(i));
                                r.add(item);
                            }
                            return r;
                        }

                        @Override
                        public boolean deleteAllItems() {
                            return false;
                        }

                        @Override
                        public Item constructItem() {
                            return null;
                        }
                    };
                }
            },
            null,
            20,
            false
        );

        lqc.addContainerProperty("name", Integer.class, null);

        Table table = new Table();
        table.setContainerDataSource(lqc);
        table.setMultiSelect(true);
        table.setSelectable(true);
        table.setImmediate(true);
        table.setVisibleColumns("name");
        table.setSizeFull();
        table.addValueChangeListener(new Property.ValueChangeListener() {
            public void valueChange(Property.ValueChangeEvent event) {
                System.err.println(event.getProperty().getValue());
            }
        });
        setContent(table);
    }
}
public类UIImpl扩展UI{
私人内部规模=500000;
@凌驾
受保护的void init(VaadinRequest请求){
//添加一个大表
LazyQueryContainer lqc=新的LazyQueryContainer(
新查询工厂(){
公共查询constructQuery(QueryDefinition qd){
返回新查询(){
@凌驾
公共整数大小(){
返回大小;
}
@凌驾
公共void保存项(列表addedItems、列表modifiedItems、列表removedItems){}
@凌驾
公共列表加载项(int startIndex,int count){
列表r=新阵列列表(计数);

对于(int i=startIndex;i如果要限制用户可以选择的行数,可以使用类似于以下代码的代码:

public class TableWithSelectionLimit extends Table {

    private final int maxSelections= -1;
    private String[] lastSelected;

    public TableWithSelectionLimit(int maxSelections) {
      this.maxSelections = maxSelections;
    }

    @Override
    public void changeVariables(Object source, Map<String, Object> variables) {
      String[] selected = (String[]) variables.get("selected");
      if (selected != null && selected.length > maxSelections) {
        if (lastSelected != null) {
          variables.put("selected", lastSelected);
        } else {
          variables.remove("selected");
        }

        markAsDirty();
      } else {
        lastSelected = selected;
      }

      super.changeVariables(source, variables);
    }
}
公共类TableWithSelectionLimit扩展表{
私有最终整数maxSelections=-1;
已选择私有字符串[];
带有选择限制的公共表(int-maxSelections){
this.maxSelections=maxSelections;
}
@凌驾
公共void变量(对象源、映射变量){
String[]selected=(String[])变量。获取(“selected”);
如果(已选择!=null&&selected.length>maxSelections){
如果(lastSelected!=null){
变量。放置(“选定”,最后选定);
}否则{
变量。删除(“选定”);
}
markAsDirty();
}否则{
lastSelected=已选择;
}
super.changeVariables(源、变量);
}
}
这当然是可以优化的,但它可以让您了解如何进行优化


更新

要处理使用“Shift”+单击产生的选择,必须在上述方法内处理/更新这些选择范围

可以使用
变量来检索这些变量。get(“selectedRanges”)
将返回一个
字符串[]
,其中包含
“8-10”
等项,而

  • 第一个数字是:选择范围的起始索引
  • 第二个数字是:从此索引开始选择的项目数量
使用此信息,应该可以根据需要更新这些值,并使用
variables.put(“selectedRanges”,updatedRanges)
将它们放回变量中


注意:不要忘记调用
markAsDirty()
如果值发生更改,则更改不会传播到客户端。

我假设
选择行
是指从数据库中检索行,而不是通过在UI表中单击来选择行。如果我是正确的,除非您有非常具体的原因,否则值得考虑不在memo中加载所有500k行Y.而是加载大小有限的块,20、50等,并以分页方式显示它们。当用户更改页面时,您将只加载其相应的行。这实际上是为了避免在UI上选择500000行的可能性。这与数据库访问无关。例如:使用惰性查询容器,选择第一个row、 向下滚动到最后一行,按住SHIFT键并选择最后一行将选择所有行-可能是500000行,即使只有少数行已加载到内存中。我希望避免分发这些500000行(我认为,这已经需要大量本地处理内存).好的,尽管如此,您是否有显示所有这些内容的要求?!在一些情况下,这将被视为一项正常要求,因为如此庞大的数字使其难以遵循和跟踪,通常会导致不太友好的结果。然而,这里的方法是通过过滤缩小范围,直到可管理。实际上(根据延迟加载)但是,你从整个数据集开始。这只是应用程序的设计。得到它,祝你好运。也许你可以考虑在DB查询中转换过滤并对结果进行分页的未来改进。这将为你节省一些OOM头衔,但这并不意味着,已经选择了500000行,IDS已经被选中了。已发送到服务器?我觉得在您测试所选的时间点。length>maxSelections,已经太晚了。如果通过单击(按住ctrl键)完成选择,则此操作有效。如果将限制设置为2,用户将无法单击表中的第三项。您希望如何进行选择?选择第一行,向下滚动到最后一行,按住SHIFT键并选择最后一行。啊,好的,我理解。在这种情况下,您也必须在此方法中处理所选的范围。您可以使用
变量获取它们。获取(“selectedRanges”)
。这将返回一个
字符串[]
包含像
8-10
这样的项目,而第一个数字是选择范围的开始索引,第二个数字是从此索引开始选择的项目数量。太好了。刚刚尝试过,它确实有效。你能将该建议添加到原始建议中,以便我可以将其标记为答案吗?