1
public class LocationBasedRole extends AbstractEntity{
    @ManyToMany(fetch=FetchType.LAZY)
    private Set<Role> roles=new HashSet<Role>();

    @ManyToMany(fetch=FetchType.LAZY)
    private Set<Location> locations=new HashSet<Location>();
}


public class Role extends AbstractEntity{
    private String name;
}


public class Location extends AbstractEntity{
    private String location;
}

我有一个名为 locationBasedRole 的实体,它有 2 个名为角色和位置的属性。角色和位置都与 locationBasedRole 具有@ManyToMany 关系。
现在我想在 Vaadin 表中拥有每个属性。
应该是这样的

public class UserForm extends OgsAbstractForm<User>{

    MTable<LocationBasedRole> locationBasedRoleTable = new MTable<LocationBasedRole>().withHeight("100%").withWidth("100%");


    @Override
    protected Component createContent() {

        Set<LocationBasedRole> lbRoles=new HashSet<LocationBasedRole>();
        roles.addAll(locationBasedRoleFasade.findAll());

        BeanItemContainer<LocationBasedRole> bean=new BeanItemContainer<LocationBasedRole>(LocationBasedRole.class);

        //It returns an error on the next both lines and I know the reason, but don't know how to solve it.
        // If it was no ManyToMany relation and the properties weren't a collection, it would work
        bean.addNestedContainerProperty("roles.name");
        bean.addNestedContainerProperty("locations.location");

        bean.removeContainerProperty("persistent");
        bean.removeContainerProperty("id");

        bean.addAll(lbRoles);

        locationBasedRoleTable.setContainerDataSource(bean);

        return new VerticalLayout(locationBasedRoleTable);
    }
}

当我从 NestedContainerProperties 中删除属性时,它至少向我显示了表格中的某些内容。

bean.addNestedContainerProperty("roles");
bean.addNestedContainerProperty("locations");

我可以使用任何帮助!

提前致谢!

4

1 回答 1

0

因此,如果我正确理解您的问题,您是否希望 BeanItemContainer-Entity 的集合分别显示在一列中?

我看到了两种可能性。

选项 1 - 为您的 s 使用包装类Set并使用addNestedContainerBean

一种可能性是不在Set您的内部使用 s ,LocationBasedRole而是使用扩展的包装类HashSet。然后你可以使用该addNestedContainerBean方法。

我用 BeanItemContainer-Entity 创建了一个小例子Team

public class Team {

    private String teamName;
    private Members teamMembers;

    public String getTeamName() {
        return teamName;
    }

    public void setTeamName(String teamName) {
        this.teamName = teamName;
    }

    public Members getTeamMembers() {
        return teamMembers;
    }

    public void setTeamMembers(Members teamMembers) {
        this.teamMembers = teamMembers;
    }
}

其中包括名称和团队成员。后者是类型Members

public class Members extends HashSet<TeamMember> {

    public String getMembers() {
        return this.stream()
                .map(member -> member.getFirstName() + " " + member.getLastName())
                .collect(Collectors.joining(","));
    }

}

这是一个Set包含以下实例的简单包装器TeamMember

public class TeamMember {

    private String firstName;
    private String lastName;
    private Integer age;

    // getters and setters
}

正如您在Members类中看到的,有一个方法getMembers返回一个字符串,其中包含一个逗号分隔的团队成员名称列表。

如果我们现在使用addNestedContainerBean("teamMembers")Vaadin 会尝试显示类中包含的所有属性Members。Vaadin 会认为 getMembers 是一个名为 members 的 String 属性的 getter,因此会为它生成一个列。

Vaadin 还将显示一列“空”,因为它会找到isEmpty方法Set并认为empty是要在列中显示的属性。所以我们告诉 Vaadin 删除该列。

我的示例的最终代码如下所示:

protected Component createContent() {

        Set<Team> teams=new HashSet<>();
        for (int teamCounter = 0; teamCounter < 5; teamCounter++) {
            Team team = createTeam();
            addMembersToTeam(5, team);
            teams.add(team);
        }

        BeanItemContainer<Team> bean=new BeanItemContainer<>(Team.class);

        bean.addNestedContainerBean("teamMembers");
        bean.removeContainerProperty("teamMembers.empty");

        bean.addAll(teams);

        teamTable.setContainerDataSource(bean);

        return new VerticalLayout(teamTable);
    }

结果如下所示:

选项1

选项 2 - 创建假吸气剂并使用addNestedContainerProperty

为此,您唯一需要做的就是扩展您的 BeanItemContainer-Entity ( ) 并为您希望在列中显示的LocationBasedRole每个创建一个虚假的 getter 。Set在您的示例中,这两个假吸气剂可能是public String getTheRoles()and public String getTheLocations()。然后你可以使用bean.addNestedContainerProperty("theRoles")and bean.addNestedContainerProperty("theLocations")

在我的示例中,我的TeamMember课程(与您的Role/Location课程相对应)仍然看起来像上面的选项:

 public class TeamMember {

    private String firstName;
    private String lastName;
    private Integer age;

    // getters and setters
}

我的Team班级(你的LocationBasedRole)看起来像:

public class Team {

    private String teamName;
    private Set<TeamMember> teamMembers;

    public String getTeamName() {
        return teamName;
    }

    public void setTeamName(String teamName) {
        this.teamName = teamName;
    }

    public Set<TeamMember> getTeamMembers() {
        return teamMembers;
    }

    public void setTeamMembers(Set<TeamMember> teamMembers) {
        this.teamMembers = teamMembers;
    }

    public String getMembers() {
        if (teamMembers != null) {
            return teamMembers.stream()
                    .map(member -> member.getFirstName() + " " + member.getLastName())
                    .collect(Collectors.joining(","));
        } else {
            return "No members";
        }
    }
}

现在您可以告诉 vaadin 添加(不存在的)属性“members”,Vaadin 将找到 gettergetMembers并使用它来生成列。我们还必须告诉 vaadin 不要显示原始的“teamMembers”属性。所以最终的代码是:

protected Component createContent() {

    Set<Team> teams=new HashSet<>();
    for (int teamCounter = 0; teamCounter < 5; teamCounter++) {
        Team team = createTeam();
        addMembersToTeam(5, team);
        teams.add(team);
    }

    BeanItemContainer<Team> bean=new BeanItemContainer<>(Team.class);

    bean.addNestedContainerProperty("members");
    bean.removeContainerProperty("teamMembers");

    bean.addAll(teams);

    teamTable.setContainerDataSource(bean);

    return new VerticalLayout(teamTable);
}

结果如下:

选项 2

于 2019-07-20T14:05:25.700 回答