How to populate modified pre-order traversal data into a Java tree object?

I have the following table with MPTT structure:

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'); 

In CakePHP, I can create the following data structure:

 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 ( ) ) ) ) ) 

The problem is how can I populate the MPTT data structure in Java using the Java tree class. Yes, I know that Java cannot have a dynamic array, as in PHP, in Java you should use the Model class.

The My Model class is as follows:

 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; } } 

I find this very confusing and I don’t know how to do it. Data coming from the database is populated with a Java tree object. I don’t know what to do, I don’t know how to completely fill it. I am using the Vivin GenericTree Java class

I think I need a data query strategy, do I need a recursive function to retrieve all the data from the database? I think that it performs two steps: 1. Request data, 2. Fill all the data to a tree object.

+4
source share
2 answers

For this, you do not need a general tree-like data structure. Consider the following example:

 private static final class Menu { private Menu parent; private List<Menu> children; private String moduleName; private String moduleControllerName; private String moduleActionName; private String alias; } 

(getters / seters for short)

The parent field helps set the parent menu and may be empty for the root menu.

Add the Children menu to the children field.

With this, you can capture the needs of your hierarchical menu, I hope.

Now, to build the query, assuming you have an rs result set:

 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... */)); } 

as for find findMenuById it could be something like:

 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; } 

change

Here is the special working implementation I made. I inserted your menu into the database and used the result set. I should be pretty much the same with your own abstraction.

 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 : I used HashMap to store a menu that is not yet attached to the root.

Note 2 : This implementation does not work if there is more than one root menu.

+2
source

You probably want to add an instance variable private Menu menu; so you can simulate a tree structure

+1
source

Source: https://habr.com/ru/post/1439997/


All Articles