Как заполнить измененные данные обхода дерева предварительного заказа в объект дерева Java?

У меня есть следующая таблица со структурой MPTT:

CREATE TABLE IF NOT EXISTS menus (
  id int(10) unsigned NOT NULL AUTO_INCREMENT,
  parent_id int(10) DEFAULT NULL,
  lft int(10) DEFAULT NULL,
  rght int(10) DEFAULT NULL,
  module_name varchar(255) DEFAULT NULL,
  module_controller_name varchar(128) DEFAULT NULL,
  module_action_name varchar(128) DEFAULT NULL,
  alias varchar(128) DEFAULT NULL,
  PRIMARY KEY (id)
) ENGINE=InnoDB;

INSERT INTO menus (`id`, `parent_id`, `lft`, `rght`, `module_name`,    
`module_controller_name`, `module_action_name`, `alias`) VALUES (1, NULL, 1, 14,  
'Root', '', '', 'Root'),
(2, 1, 2, 7, 'Toolbox', '', '', 'Toolbox'),
(3, 2, 5, 6, 'Menu Manajemen', 'menus', 'index', 'MenuManajemenz'),
(4, 2, 3, 4, 'Hak Akses Manajemen', 'access_rights', 'index', 'HakAksesManajemen'),
(5, 1, 8, 13, 'Accounts', '', '', 'Accounts'),
(6, 5, 9, 10, 'Users', 'users', 'index', 'Users'),
(7, 5, 11, 12, 'Groups', 'groups', 'index', 'Groups');

В CakePHP я могу создать следующую структуру данных:

Array
(
    [0] => Array
        (
            [Menu] => Array
                (
                    [id] => 2
                    [parent_id] => 1
                    [lft] => 2
                    [rght] => 7
                    [module_name] => Toolbox
                    [module_controller_name] => 
                    [module_action_name] => 
                    [alias] => Toolbox
                )

            [children] => Array
                (
                    [0] => Array
                        (
                            [Menu] => Array
                                (
                                    [id] => 4
                                    [parent_id] => 2
                                    [lft] => 3
                                    [rght] => 4
                                    [module_name] => Hak Akses Manajemen
                                    [module_controller_name] => access_rights
                                    [module_action_name] => index
                                    [alias] => HakAksesManajemen
                                )

                            [children] => Array
                                (
                                )

                        )

                    [1] => Array
                        (
                            [Menu] => Array
                                (
                                    [id] => 3
                                    [parent_id] => 2
                                    [lft] => 5
                                    [rght] => 6
                                    [module_name] => Menu Manajemen
                                    [module_controller_name] => menus
                                    [module_action_name] => index
                                    [alias] => MenuManajemenz
                                )

                             [children] => Array
                                (
                                )

                        )

                 )

         )
    )

Проблема заключается в том, как заполнить структуру данных MPTT в Java, используя древовидный класс Java. Да, я знаю, что в Java не может быть динамического массива, как в PHP, в Java нужно использовать класс Model .

Мой класс модели выглядит так:

public class Menu {
    private String moduleName;
    private String moduleControllerName;
    private String moduleActionName;
    private String alias;

    public String getModuleName() {
        return moduleName;
    }

    public void setModuleName(String moduleName) {
        this.moduleName = moduleName;
    }

    public String getModuleControllerName() {
        return moduleControllerName;
    }

    public void setModuleControllerName(String moduleControllerName) {
        this.moduleControllerName = moduleControllerName;
    }

    public String getModuleActionName() {
        return moduleActionName;
    }

    public void setModuleActionName(String moduleActionName) {
        this.moduleActionName = moduleActionName;
    }

    public String getAlias() {
        return alias;
    }

    public void setAlias(String alias) {
        this.alias = alias;
    }
}

Я нахожу это очень запутанным, и я не знаю, как это сделать. Данные, поступающие из базы данных, заносятся в объект дерева Java. Я не знаю, что делать, я не знаю, как заполнить его полностью. Я использую GenericTree от Vivin Java класс

Я думаю, мне нужна стратегия запроса данных, нужна ли рекурсивная функция для извлечения всех данных из базы данных? Я думаю, что это занимает два шага: 1. Запрос данных, 2. Заполнение всех данных древовидным объектом.


person Oka Prinarjaya    schedule 16.10.2012    source источник
comment
@Bob ~ привет, Боб :) что ты редактируешь? спасибо за рассмотрение моего вопроса. если вы знаете решение, пожалуйста, помогите Бобу :)   -  person Oka Prinarjaya    schedule 16.10.2012


Ответы (3)


Для этого вам не нужна общая древовидная структура данных. Рассмотрим следующий пример:

private static final class Menu {
    private Menu parent;
    private List<Menu> children;

    private String moduleName;
    private String moduleControllerName;
    private String moduleActionName;
    private String alias;
}

(геттеры/сеттеры опущены для краткости)

Поле parent помогает вам установить родительское меню и может быть нулевым для корневого меню.

Добавьте меню «Дети» в поле children.

С этим вы сможете уловить потребности вашего иерархического меню, я надеюсь.

Теперь, чтобы построить запрос, предположим, что у вас есть набор результатов rs:

Menu menu;

while (rs.hasNext()) {
    if (rs.get("parent_id") == null) {
        // it s the root
        menu = new Menu(rs.get("id"), /* etc... */);
    } else {
        menu = findMenuById(menu, rs.get("parent_id"));
        menu.addChild(new Menu(rs.get("id"), /* etc... */));
}

что касается find findMenuById, это может быть что-то вроде:

private Menu findMenuById(Menu menu, Long id) {
    if (menu.getId() == id) return menu;
    for (Menu childMenu : menu.getChildren()) {
        Menu found = findMenuById(childMenu, id);
        if (found != null) return found;
    }
    return null;
}

редактировать

Вот пользовательская рабочая реализация, которую я сделал. Я вставил ваше меню в базу данных и использую набор результатов. Я должен быть почти таким же с вашей пользовательской абстракцией.

Menu root = null;
        Map<Integer, Menu> menus = new HashMap<Integer, Menu>();

        final Database databaseConnection = Database.createConnection("test", "root", "");
        final ResultSet rs = databaseConnection.executeQuery("SELECT * FROM test.menus;");
        while ( rs.next() ) {
            final Menu menu = new Menu(rs.getInt("id"))
                .setAlias(rs.getString("alias"))
                .setModuleName(rs.getString("module_name"));

            final Integer parentId = rs.getInt("parent_id");
            if (root == null && parentId == 0) {
                root = menu;
            } else {
                menus.get(parentId).addSubMenu(menu);
            }

            menus.put(menu.getId(), menu);
        }

        rootMenu = root;

        databaseConnection.closeConnection();

Note 1: Я использовал HashMap для хранения меню, которые еще не привязаны к корню.

Note 2: Эта реализация не будет работать, если есть более одного корневого меню.

person phury    schedule 16.10.2012
comment
Спасибо. Но какова структура SQL-запроса для этой проблемы? нужна ли рекурсивная функция для извлечения всех данных из базы данных? Я ничего не знаю об этом. Как определить, является ли строка родительской? тогда? - person Oka Prinarjaya; 16.10.2012
comment
Хммм... думаю, мне нужна стратегия запроса данных. Ааа сложно сказать.. :( - person Oka Prinarjaya; 16.10.2012
comment
Спасибо тел. Я попробую ваше решение. И завтра я вернусь снова. спасибо большое - person Oka Prinarjaya; 16.10.2012
comment
Halo, я попробовал ваше решение, но все еще не могу заставить его работать :( я отредактировал свой вопрос, чтобы объяснить, что я сделал. Извините, я впервые использую stackoverflow. - person Oka Prinarjaya; 17.10.2012
comment
это то, что я сделал. Но я все еще не могу заставить его работать :( pastie.org/5072156 и pastie.org/5072174 . Все еще ошибка возвращает NULL. Я не уверен, что дерево заполнено. здесь pastie.org/5072174 мои данные инкапсулированы List‹Exploration› , я использую библиотеку абстракции базы данных моей компании. Поэтому я не извлекаю свои данные с помощью while (rs .hasNext()) { - person Oka Prinarjaya; 17.10.2012
comment
где у тебя ноль? любая информация будет полезна, например, трассировка стека - person phury; 26.10.2012
comment
не знаю что делать я в замешательстве - person Oka Prinarjaya; 29.10.2012

Вероятно, вы захотите добавить переменную экземпляра private Menu menu;, чтобы можно было моделировать древовидную структуру.

person David Soroko    schedule 16.10.2012

Возможно, вам будет полезно проверить эту реализацию MPTT на Java JPA. Демонстрация в исходном коде может дать идеи о том, как смоделировать вашу сущность, а также заполнить дерево.

https://github.com/hacker-works/mptt-jpa

person Vladimir Tsvetkov    schedule 01.07.2020