当前位置: 首页 > news >正文

Vaadin Grid列配置:避免“同一属性多列”异常

本文旨在解决Vadin的问题 Grid中常见的“Multiple columns for the same property“异常。这个问题通常源于对Grid初始化和列添加方法的误用。当使用new时 Grid(Entity.class)构造函数时,Vaadin Grid将自动创建实体类的所有公共属性列;如果以后通过grid.addColumns("propertyName“)在显式中添加同名列会导致重复定义和抛出异常。本文将详细解释这一机制,并提供正确的列配置方法,以帮助开发人员有效地管理Grid显示列。Vaadin Grid列配置机制分析

Vaadin Grid是一个强大的数据表组件,它提供了多种定义和管理列显示的方法。了解这些机制是避免常见配置错误的关键。

  1. 基于实体类的自动列生成 当您使用new时 Grid(YourEntityClass.class)当构建函数初始化Grid时,Vaadin Grid将智能地检查YourentityClass中的所有公共geter方法(如getauditid()、getTrip()等),并自动为每个可识别的属性创建一个列。这意味着,如果您有一个叫做auditid的属性,并且有一个相应的方法来获取auditid(),那么grid已经自动创建了一个列来显示auditid数据。

    // 例:Grid初始化时自动创建列 Grid<Audit> grid = new Grid<>(Audit.class); // 此时,grid已经包含了auditid、trip、user、enterprise等列
  2. 显式添加列Grid组件还提供了addcolumns()方法,允许开发者显式指定要显示的属性名,从而添加新列。

    // 示例:显式添加列 grid.addColumns("propertyname1", "propertyname");

    当Grid未通过实体结构或需要添加非实体属性(如计算属性)时,通常使用此方法。

“Multiple columns for the same property根源异常

问题的核心是上述两种机制的混合。当您首先使用new时 Grid(Audit.class)对Grid进行初始化,使其自动为Audit实体创建所有列(包括AuditID),然后在构造函数中显式调用Grid.addColumns("auditId“)当试图再次添加auditid列时,Vadin将检测到两次定义相同属性的auditid。这违反了Grid的内部一致性,因此抛出了Illegalargumentexception: Multiple columns for the same property: auditid异常。

问题代码示例:

// EnterpriseView.java public class EnterpriseView extends VerticalLayout implements HasUrlParameter<String>, AfterNavigationObserver{ // ... 其它成员变量和构建函数 public EnterpriseView(EnterpriseDao enterpriseDao, AuditDao auditDao) { this.enterpriseDao = enterpriseDao; this.auditDao = auditDao; this.grid = new Grid<>(Audit.class); // 1. Grid自动为Audit实体创建所有列,包括auditid VerticalLayout layout = new VerticalLayout(); layout.add(grid); grid.addColumns( "auditId" ); // 2. auditid列再次显式添加,导致重复 } // ... 其他方法 }

解决方案

为了解决这种异常,您需要确保每个属性只被Grid添加到一个列中。根据您的需要,有两个主要的解决方案:

  1. 依靠自动生成,删除不必要的列(如果需要显示大部分列) 如果你想让Grid自动生成大部分列,但又想定制或删除某些列,你可以继续使用new Grid(Audit.class),然后使用removecolumn()或setcolumns()进行调整。

    // 解决方案1:依靠自动生成、删除或定制 public EnterpriseView(EnterpriseDao enterpriseDao, AuditDao auditDao) { this.enterpriseDao = enterpriseDao; this.auditDao = auditDao; this.grid = new Grid<>(Audit.class); // 自动创建所有列表的Grid // 例子:如果只需要auditidid、trip、user,enterprise列可以移除 // grid.removeColumn(grid.getColumnByKey("enterprise")); // 假设enterprise列的key是"enterprise" // 或者,如果您想完全控制显示列,可以使用setcolumns // grid.setColumns("auditId", "trip", "user"); // 只显示这三列 VerticalLayout layout = new VerticalLayout(); layout.add(grid); // 不再调用 grid.addColumns("auditId"); }
  2. 不使用实体结构函数,手动添加所有所需列(如果只需要显示少数列或精细控制) 如果您只是想显示Audit实体中的几个特定列,或者需要更好地控制每个列(如自定义渲染器),最好不要将实体引入构造函数,而是手动添加所有列。

    // 解决方案2:手动添加所有所需列表 public EnterpriseView(EnterpriseDao enterpriseDao, AuditDao auditDao) { this.enterpriseDao = enterpriseDao; this.auditDao = auditDao; this.grid = new Grid<>(); // 不进入实体类,Grid最初是空的 VerticalLayout layout = new VerticalLayout(); layout.add(grid); // 手动添加所有需要的列 grid.addColumns("auditId", "trip", "user", "enterprise"); // 添加所有需要的列 // 或者使用 addColumn 配置方法比较复杂,例如: // grid.addColumn(Audit::getAuditId).setHeader("审计ID"); // grid.addColumn(audit -> audit.getTrip().getName()).setHeader("行程名称"); // 示例:访问相关实体的属性 }

    在你提供的场景中,因为grid.addColumns("auditId“)是唯一显式添加列的地方,最直接的修复就是删除这一行代码,因为new Grid(Audit.class)auditid列的创建已经为您处理好了。

修改后的代码示例

基于以上分析,最简单有效的修正方法是删除重复的adddcolumns调用。

import com.vaadin.flow.component.grid.Grid; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.*; import com.wtd.assistant.frontend.dao.AuditDao; import com.wtd.assistant.frontend.dao.EnterpriseDao; import com.wtd.assistant.frontend.domain.Audit; import com.wtd.assistant.frontend.domain.Enterprise; import java.util.List; import java.util.Optional; @Route("EnterpriseView") public class EnterpriseView extends VerticalLayout implements HasUrlParameter<String>, AfterNavigationObserver{ private EnterpriseDao enterpriseDao; private AuditDao auditDao; private Grid<Audit> grid; private List<Audit> auditsList; private Optional<Enterprise> enterprise; private String enterpriseId; public EnterpriseView(EnterpriseDao enterpriseDao, AuditDao auditDao) { this.enterpriseDao = enterpriseDao; this.auditDao = auditDao; this.grid = new Grid<>(Audit.class); // Vaadin 自动创建auditid列的Grid VerticalLayout layout = new VerticalLayout(); layout.add(grid); // 删除以下重复行: // grid.addColumns( "auditId" ); } @Override public void setParameter(BeforeEvent event, String parameter) { enterpriseId = parameter; System.out.println("setParameter(), enterpriseId: " + enterpriseId); } @Override public void afterNavigation(AfterNavigationEvent event) { enterprise = enterpriseDao.findById(Integer.valueOf(enterpriseId)); System.out.println("EnterpriseId: " + enterprise.get().getEnterpriseId()); auditsList = enterprise.get().getAudits(); grid.setItems(auditsList); } }

注意事项和最佳实践

  • 明确列的来源: 在配置Grid时,始终明确您希望列是如何生成的。它完全自动化(new Grid(Class.class)),还是完全手动(new Grid()后跟adddcolumn或addcolumns),或自动生成后微调。
  • 高级定制采用adddcolumn: 对于需要定制渲染器、设置列宽、对齐或访问相关对象属性的列,建议使用addcolumn(ValueProvider valueProvider)方法。例如,显示相关Trip实体的名称:
    grid.addColumn(audit -> audit.getTrip().getName()) .setHeader("行程名称") .setKey("tripName"); // 为列设置唯一的key
  • 使用setColumns控制显示: 如果您希望Grid只显示实体中特定子集的属性,而不是所有自动生成的属性,可以使用setcolumns(prop1), “prop2”, ...)。这将清除所有现有列并添加指定的新列。
  • 列的顺序: addColumns()和adddcolumn()将按调用顺序添加列。setColumns()按参数顺序设置列。

总结Vaadin “Grid”Multiple columns for the same property由于Grid自动列生成机制和显式列添加方法的混淆,异常是一种典型的配置错误。通过理解new Grid(Class.class)开发人员可以轻松解决自动行为,避免重复添加现有列。根据具体需要,选择完全依赖自动生成、完全手动配置或组合使用的方法,可以更有效地管理Vadin Grid列显示。

http://www.jsqmd.com/news/550717/

相关文章:

  • 激光热致等离子体模型的Comsol模拟研究及结果分析
  • 医学影像分割新宠:拆解UNETR++中的‘配对注意力’(EPA),它比CBAM强在哪?
  • Python自动化CAD设计:从基础操作到高级应用
  • 利用快马平台快速生成clawx工具的功能演示原型
  • QAnything版本升级指南:从1.3到1.4的关键变更
  • Lingbot-Depth-Pretrain-ViTL-14实战:为微信小程序提供实时深度估计能力
  • Structured Outputs 实战:让大模型稳定输出 JSON 的三种方案对比
  • Kerberos并发认证难题:解析kinit缓存冲突与KRB5CCNAME的实战应用
  • 使用VSCode调试PDF-Parser-1.0模型的完整指南
  • 3分钟快速上手:零基础用AI自动生成高质量解说视频的完整指南
  • APK-Installer终极指南:在Windows电脑上快速安装安卓应用的完整教程
  • 告别驱动烦恼:在Windows上用Electron + noble-winrt搞定蓝牙通信(保姆级避坑指南)
  • Mist工具:如何一站式解决macOS固件和安装程序管理难题?
  • Windows 7/Vista终极救星:如何在老旧系统上安装最新Python 3.14?
  • 探索LSPosed:Android Hook技术实战指南
  • 决策树算法对比:ID3 vs C4.5 从原理到实战(含数据集和Python示例)
  • 一文讲透|盘点2026年实力封神的的降AIGC工具
  • 手把手教你用频谱仪测试电磁屏蔽效果(附Python数据分析代码)
  • 3种方法让Mac鼠标秒变生产力神器:Mac Mouse Fix终极安装指南
  • 解决RColorBrewer颜色不够用的问题:手把手教你扩展配色方案
  • Kali Linux下快速安装蚁剑的3种方法(附常见错误解决方案)
  • java怎样使用泛型提高代码安全性
  • 5分钟搞定Qwen2.5-3B-Instruct-GGUF本地部署(附OpenAI API调用指南)
  • TFT实战指南:从理论到代码,构建可解释的多步时间序列预测系统
  • 告别Xcode臃肿,用Trae IDE在Mac上搭建轻量级C++开发环境(附完整配置文件)
  • AI专著写作新突破!高效工具助力,轻松打造百万字专著
  • 多维时序预测应用 Transformer-BILSTM
  • 跨平台方案:Windows与Mac共享百川2-13B-4bits模型服务
  • 三步解锁多平台资源下载工具:轻松解决视频、音乐保存难题
  • foobox-cn:重构foobar2000体验的DUI配置方案