Hi Mike,
I apologise because I made some mistake into use your suggest!
Now the fase of retriev has improved performance.
The problem was inside my original code ( that I don't had posted ).
I had put the 'data' field in a external object; so as you suggested me I take a look to the sql trace I see thousands of the sql rows.
I suppose that the over loading be to bind to the external object.
Have some comments about ?
The Original Node
Code:
@Entity
public class Node<T> implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
public T data;
private Node<T> parent;
public List<Node<T>> children;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Node() {
super();
}
public Node(T data) {
this();
setData(data);
}
@OneToMany(mappedBy = "parent", targetEntity = Node.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
public List<Node<T>> getChildren() {
if (this.children == null) {
return new ArrayList<Node<T>>();
}
return this.children;
}
public void setChildren(List<Node<T>> children) {
this.children = children;
}
@Transient
public int getNumberOfChildren() {
if (children == null) {
return 0;
}
return children.size();
}
@Transient
public void addChild(Node<T> child) {
if (children == null) {
children = new ArrayList<Node<T>>();
}
children.add(child);
child.setParent(this);
}
@Transient
public void insertChildAt(int index, Node<T> child) throws IndexOutOfBoundsException {
if (index == getNumberOfChildren()) {
addChild(child);
return;
} else {
children.get(index);
children.add(index, child);
}
}
@Transient
public void removeChildAt(int index) throws IndexOutOfBoundsException {
children.remove(index);
}
@OneToOne(targetEntity = Data.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
public T getData() {
return this.data;
}
public void setData(T data) {
Method metodo;
try {
metodo = data.getClass().getMethod("setOwner", new Class[] { this.getClass() });
if (metodo != null)
metodo.invoke(data, new Object[] { this });
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
this.data = data;
}
@Transient
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{").append(getData().toString()).append(",[");
int i = 0;
for (Node<T> e : getChildren()) {
if (i > 0) {
sb.append(",");
}
sb.append(e.getData().toString());
i++;
}
sb.append("]").append("}");
return sb.toString();
}
@ManyToOne(targetEntity = Node.class,fetch=FetchType.EAGER)
@JoinColumn(name = "pid")
public Node<T> getParent() {
return parent;
}
public void setParent(Node<T> parent) {
this.parent = parent;
}
}
The DataCode:
@Entity
public class Data implements Serializable{
private static final long serialVersionUID = 1L;
private Long id;
private Node<Data> owner;
private String codice;
private String descri;
private Boolean attivaVarianti;
private Object obj;
private List<RigaH> righe;
public Data(){
super();
}
public Data( String codice ){
this();
this.codice = codice;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@OneToOne(mappedBy = "data")
public Node<Data> getOwner() {
return owner;
}
public void setOwner(Node<Data> owner) {
this.owner = owner;
}
public String getDescri() {
return descri;
}
public void setDescri(String descri) {
this.descri = descri;
}
public Boolean getAttivaVarianti() {
return attivaVarianti;
}
public void setAttivaVarianti(Boolean attivaVarianti) {
this.attivaVarianti = attivaVarianti;
}
public void setAttivaVarianti(String attivaVarianti) {
this.attivaVarianti = Boolean.parseBoolean(attivaVarianti);
}
public String getCodice() {
return codice;
}
public void setCodice(String codice) {
this.codice = codice;
}
@Transient
public List<RigaH> getRighe() {
return righe;
}
public void setRighe(List<RigaH> righe) {
this.righe = righe;
}
@Transient
public void addRiga(RigaH riga) {
if (righe == null) {
righe = new ArrayList<RigaH>();
}
righe.add(riga);
}
@Transient
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
}
Now I put direct the data inside the node and the loading of the tree is more fast!
The new NodeCode:
@Entity
public class Node implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private Node parent;
public List<Node> children;
private String codice;
private String descri;
private Boolean attivaVarianti;
private Object obj;
private List<RigaH> righe;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Node() {
super();
}
public Node(String codice) {
this();
setCodice(codice);
}
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
public List<Node> getChildren() {
if (this.children == null) {
return new ArrayList<Node>();
}
return this.children;
}
public void setChildren(List<Node> children) {
this.children = children;
}
@Transient
public int getNumberOfChildren() {
if (children == null) {
return 0;
}
return children.size();
}
@Transient
public void addChild(Node child) {
if (children == null) {
children = new ArrayList<Node>();
}
children.add(child);
child.setParent(this);
}
@Transient
public void insertChildAt(int index, Node child) throws IndexOutOfBoundsException {
if (index == getNumberOfChildren()) {
// this is really an append
addChild(child);
return;
} else {
children.get(index);
children.add(index, child);
}
}
@Transient
public void removeChildAt(int index) throws IndexOutOfBoundsException {
children.remove(index);
}
@Transient
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{").append(getCodice()).append(",[");
int i = 0;
for (Node e : getChildren()) {
if (i > 0) {
sb.append(",");
}
sb.append(e.getCodice().toString());
i++;
}
sb.append("]").append("}");
return sb.toString();
}
public String getCodice() {
return codice;
}
public void setCodice(String codice) {
this.codice = codice;
}
public String getDescri() {
return descri;
}
public void setDescri(String descri) {
this.descri = descri;
}
public Boolean getAttivaVarianti() {
return attivaVarianti;
}
public void setAttivaVarianti(Boolean attivaVarianti) {
this.attivaVarianti = attivaVarianti;
}
public void setAttivaVarianti(String attivaVarianti) {
this.attivaVarianti = Boolean.parseBoolean(attivaVarianti);
}
@ManyToOne
@JoinColumn(name = "pid")
public Node getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
@Transient
public List<RigaH> getRighe() {
return righe;
}
public void setRighe(List<RigaH> righe) {
this.righe = righe;
}
@Transient
public void addRiga(RigaH riga) {
if (righe == null) {
righe = new ArrayList<RigaH>();
}
righe.add(riga);
}
@Transient
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
}
Ok, you are ask me, about what to do with this tree...
I want to load a tree of many artical, with group of kinds, and show to user this...
So I use this tree only in memory and I not serializated it.
Perhaps exist a method to load in memory without use the transaction ( that i think has a cost )?
Have some comments about ?
And, of course, many thanks