“我的班级类别”本身可以具有parentCategory
或作为根Category
,然后将parentCategory
设置为null
。每个Category
可能都有子类别
我的Category
类的代码:
public class Category extends AbstractEntity<Integer> {
@ManyToOne(cascade = { CascadeType.ALL, CascadeType.REMOVE })
@JoinColumn(name = "parentCategory_id")
private Category parentCategory;
@OneToMany(mappedBy = "parentCategory", fetch = FetchType.EAGER)
private Set<Category> subcategories;
private String name;
@OneToMany(cascade = { CascadeType.ALL, CascadeType.REMOVE }, fetch = FetchType.EAGER)
private List<Item> items;
public Category(String name) {
this.subcategories = new HashSet<>();
this.name = name;
this.items = new ArrayList<>();
}
...
}
假设我的数据库中有很多带有子类别的类别。我想用javafx的TreeView
来显示类别的层次结构,但是要以通用的方式显示而无需手动填充TreeItem
。不幸的是,我可以轻松地仅显示根类别的直接子类别
我测试过的代码:
public void initialize(URL paramURL, ResourceBundle paramResourceBundle) {
List<Category> categoriesAll = categoryDao.findAll();
categories.getSelectionModel().selectedItemProperty()
.addListener((ObservableValue<? extends Category> observable, Category oldValue, Category newValue) -> {
});
categories.getItems().addAll(FXCollections.observableArrayList(categoriesAll));
TreeItem<String> rootNode = new TreeItem<>("Categories");
rootNode.setExpanded(true);
List<Category> superCategories = categoriesAll.stream().filter(category -> !category.hasParentCategory())
.collect(Collectors.toList());
Map<Category, TreeItem<String>> nodesMap = new HashMap<>();
for (Category cat : superCategories) {
TreeItem<String> leaf = new TreeItem<String>(cat.getName());
addTreeItems(0, cat, nodesMap);
rootNode.getChildren().add(leaf);
}
rootNode.getChildren().get(0).getChildren().add(nodesMap.entrySet().stream()
.filter(entry -> entry.getKey().getName().equals("automotive")).findFirst().get().getValue());
categoriesTree.setRoot(rootNode);
}
public void addTreeItems(int index, Category category, Map<Category, TreeItem<String>> nodesMap) {
// System.out.println(index + " " + category.getName());
nodesMap.put(category, new TreeItem<String>(category.getName()));
List<TreeItem<String>> childrenCategories = category.getSubcategories().stream()
.map(c -> new TreeItem<String>(c.getName())).collect(Collectors.toList());
nodesMap.get(category).getChildren().addAll(childrenCategories);
category.getSubcategories().forEach(cat -> addTreeItems(index + 1, cat, nodesMap));
}
输出为(在treeView组件中):
automotive
|_tires and rims
|_auto parts
|_cars
|_car workshop equipment
但是应该是:
automotive
|_tires and rims
| |_winter tires
| |_summer tires
|_auto parts
|_cars
| |_audi
| | |_a4
| |_nissan
| |_gtr
|_car workshop equipment
答案 0 :(得分:0)
因此,我为嵌套数据层次结构的问题提出了解决方案。解决此问题的方法是找到没有父项的根类别。
List<Category> superCategories = categoriesAll.stream().filter(category -> !category.hasParentCategory())
.collect(Collectors.toList());
然后将每个superCategory
视为根本身:
TreeItem<String> rootNode = new TreeItem<>("Categories");
rootNode.setExpanded(true);
superCategories.forEach(superCategory -> Utils.buildRoot(superCategory, rootNode));
buildRoot
方法:
public static void buildRoot(Category category, TreeItem<String> root) {
if (category.hasParentCategory()) {
TreeItem<String> found = find(root, category.getParentCategory().getName());
if (found != null) {
found.getChildren().add(new TreeItem<String>(category.getName()));
}
} else {
root.getChildren().add(new TreeItem<String>(category.getName()));
}
category.getSubcategories().forEach(subcategory -> buildRoot(subcategory, root));
}
find
方法:
private static TreeItem<String> find(TreeItem<String> root, String value) {
if (root != null) {
if (root.getValue().equals(value)) {
return root;
}
ObservableList<TreeItem<String>> children = root.getChildren();
if (children != null) {
for (TreeItem<String> child : children) {
if (child.getValue().equals(value)) {
return child;
}
return find(child, value);
}
}
}
return null;
}