patternjavaMinor
Make the tree from a database into a tree of Java
Viewed 0 times
theintomakejavadatabasefromtree
Problem
There is a task to get the data from the database (tree) and translate them into Java. They must maintain their properties (each entry has parent and descendants).
I'm taking data from database using Statement and ResultSet. The output is an arraylist of
Now we need to convert this array into the likeness of a tree.
How I do it:
Where
Isn't that code redundant? Is there a more elegant solution?
I'm taking data from database using Statement and ResultSet. The output is an arraylist of
RowNode: public class RawNode {
int id;
int parentId;
String text;
//getters&setters here
}Now we need to convert this array into the likeness of a tree.
How I do it:
public List makeNewTree(ArrayList _rawNode) {
List nodes = new ArrayList<>(_rawNode.size());
Map rawNodesByNodes = new HashMap<>(_rawNode.size()+10, 0.98f);
Map nodesById = new HashMap<>(_rawNode.size()+10, 0.98f);
try {
for (RawNode rawNode : _rawNode) {
Node node = new Node();
node.setId(rawNode.getId());
node.setText(rawNode.getText());
rawNodesByNodes.put(node, rawNode);
nodesById.put(rawNode.getId(), node);
nodes.add(node);
}
for (Node node : nodes) {
RawNode rawNode = rawNodesByNodes.get(node);
Integer parentId = rawNode.getParentId();
if (parentId == null) {
node.setParent(null);
} else {
Node parent = nodesById.get(parentId);
node.setParent(parent);
}
}
for (Node node : nodes) {
Node parentNode = node.getParent();
if (parentNode == null) {
continue;
}
parentNode.addChild(node);
}
} catch (Exception ex) {...}
return nodes;
}Where
Node is:public class Node {
private int id;
private Node parent;
private String text;
private List children = new ArrayList<>();
}Isn't that code redundant? Is there a more elegant solution?
Solution
OR-mapping
You fall into the object-relational impedance problem.
RawNode seems to be the same as Node but they are totally different in purpose. This doesn't even change if you use an OR-Mapper like Hibernate.
The following definitions assume you do not want to have an anemic domain model.
RawNode (mapping object)
It provides a concrete representation what came from the database. It is a datastructure only with no logic. It abstracts from the raw resultset where you access columns via column names or indices.
A RawNode is used as a datastructure to communicate with the database through the DAOs in both ways. A RawNode object is a value object. It has no assertion to consistency. You may check the values for consistency (e.g. Java Validation API) and get a list of constraint violations. But the current state of the object may be inconsistent. OR-Mapper can do validations but as they are not able to enforce business rules I would not rely on this.
Equality of these type of objects should be checked either be on all values or on none.
Node (business object)
Equality of a business object is checked on a global unique id.
This is a real business object. It has the assertion to be immutable in the current version. If the non unique values are different but the id is the same you have a different version of the business object. But it is the same object. A business object is ALWAYS consistent in respect to the information it provides. If it is not this is an error. Business objects enforce business rules and consistency when you try to make a change. They will process validation and structural checks to keep the whole system consistent.
Useful assertions
As you remap the business object to the mapping object in the DAO you can be sure that the communication object is consistent as the business object was consistent.
As you remap an unmodified mapping object from the database to a business object you can assume consistency.
Your code
Avoid continue
multiple return, break and continue are not refactring-friendly. They make it hard to extract methods if you want to sub divide a method.
What kind of exception do you expect?
You have all transient datastructure available. Do you expect a NullPointerException because a parent that was defined could not be found? If that is the case you should fix the algorithm that produces that inconsistency and not try to straighten it for further algorithms. The decision to fix the data is depending on your influence on the data holder of course.
Extract methods
Extract the following responsibilities into separate methods:
1. Build Nodes without parents and children from RawNodes
2. Build a temporaray map with Node by Id
3. Set parent child relationship
You fall into the object-relational impedance problem.
RawNode seems to be the same as Node but they are totally different in purpose. This doesn't even change if you use an OR-Mapper like Hibernate.
The following definitions assume you do not want to have an anemic domain model.
RawNode (mapping object)
It provides a concrete representation what came from the database. It is a datastructure only with no logic. It abstracts from the raw resultset where you access columns via column names or indices.
A RawNode is used as a datastructure to communicate with the database through the DAOs in both ways. A RawNode object is a value object. It has no assertion to consistency. You may check the values for consistency (e.g. Java Validation API) and get a list of constraint violations. But the current state of the object may be inconsistent. OR-Mapper can do validations but as they are not able to enforce business rules I would not rely on this.
Equality of these type of objects should be checked either be on all values or on none.
Node (business object)
Equality of a business object is checked on a global unique id.
This is a real business object. It has the assertion to be immutable in the current version. If the non unique values are different but the id is the same you have a different version of the business object. But it is the same object. A business object is ALWAYS consistent in respect to the information it provides. If it is not this is an error. Business objects enforce business rules and consistency when you try to make a change. They will process validation and structural checks to keep the whole system consistent.
Useful assertions
As you remap the business object to the mapping object in the DAO you can be sure that the communication object is consistent as the business object was consistent.
As you remap an unmodified mapping object from the database to a business object you can assume consistency.
Your code
Avoid continue
multiple return, break and continue are not refactring-friendly. They make it hard to extract methods if you want to sub divide a method.
What kind of exception do you expect?
You have all transient datastructure available. Do you expect a NullPointerException because a parent that was defined could not be found? If that is the case you should fix the algorithm that produces that inconsistency and not try to straighten it for further algorithms. The decision to fix the data is depending on your influence on the data holder of course.
Extract methods
Extract the following responsibilities into separate methods:
1. Build Nodes without parents and children from RawNodes
2. Build a temporaray map with Node by Id
3. Set parent child relationship
Context
StackExchange Code Review Q#155522, answer score: 2
Revisions (0)
No revisions yet.