Hi George As I said, my hibernate is a bit rusty. What I have given you there is a JDBC query where each question mark represents a parameter which is later set by Query.setLong(int paramIndex, Long value). You might need to research or chat on hibernate forums to turn it into a hibernate friendly query. Actually, I just looked at the hibernate javadoc and it says that it supports JDBC style '?' parameters so it might just work but I'm not 100%. You could always look at using a hibernate criteria query and using a projection to get the count() of children. Again, ask on the hibernate forums for this.
<rant> I actually really dislike hibernate because I think it makes smart people write stupid code. I have turned on SQL logging on hibernate applications only to be disgusted by seeing many unnecessary extra queries, joins and n+1 selects issues. If the developers were coding their queries by hand, this would have never happened. I happen to prefer iBatis / myBatis for it's hands on approach. Since the db is often the slowest component in your system, I hate to be so far abstracted from it. </rant> Apart from that your code looks ok although I would probably make the DAO a service and add it to Tapestry's IOC registry and then @Inject the DAO. What you have at the moment should work though so it's probably best to get the query working first. Good luck, Lance. On Thursday, 16 February 2012, George Christman <gchrist...@cardaddy.com> wrote: > Hi Lance, I'd like to share my progress with you. I think it will work once > we get the hibernate sql query corrected. If you wouldn't mind taking a > brief look at my classes to be sure I implemented everything correctly, it > would be greatly appreciated. I could always get a little assistance from > the hibernate guys too if we can't figure out that query. I seen a ? in the > question stringbuilder method. Is that a place holder or is there some kind > of logic behind it. Once again thanks, > > Cheers, > George > > @Entity > public class Category extends BaseEntity { > > private String label; > > @OneToMany(mappedBy = "parentCategoryId") > private List<Category> children; > > @ManyToOne > @JoinColumn(name = "parent_id") > private Category parentCategoryId; > > //Getters Setters > > > > > > public class CategoryNode { > > private Category category; > private boolean isLeaf; > private boolean hasChildren; > > //Getters Setters > > > > > > public class HibernateCategoryDao implements CategoryDao { > > private final Session session; > > public HibernateCategoryDao(Session session) { > this.session = session; > } > > // this will be called by ValueEncoder.toValue(id) > public CategoryNode findById(String id) { > return findByCriterion(Restrictions.eq("categoryId", > id)).iterator().next(); > } > > // this will be called by TreeModelAdapter.getChildren(CategoryNode > node) > public List<CategoryNode> getChildren(CategoryNode node) { > return findByCriterion(Restrictions.eq("parentCategoryId", > node.getCategory())); > } > > // this will be called by your page > public List<CategoryNode> findRoots() { > return findByCriterion(Restrictions.isNull("parentCategoryId")); > } > > @SuppressWarnings("unchecked") > protected List<CategoryNode> findByCriterion(Criterion criterion) { > List<Category> cats = > session.createCriteria(Category.class).add(criterion).list(); > Map<Integer, CategoryNode> childNodes = new LinkedHashMap<Integer, > CategoryNode>(); > for (Category cat : cats) { > CategoryNode childNode = new CategoryNode(); > childNode.setCategory(cat); > childNodes.put(cat.getId(), childNode); > } > StringBuilder questions = new StringBuilder(); > for (int i = 0; i < childNodes.size(); ++i) { > if (i != 0) { > questions.append(", "); > } > questions.append("?"); > } > > > Query query = session.createSQLQuery( > "select c1.id, count(c2.*) " > + "from Category c1 " > + "left join Category c2 on c2.parentCategoryId = c1.id " > + "where c1.id in (" + questions + ") " > + "group by c1.id"); > > int i = 0; > > for (Iterator<CategoryNode> it = > childNodes.values().iterator(); i < childNodes.size(); ++i) { > query.setLong(i + 1, > it.next().getCategory().getId()); > } > > for (Iterator<Object[]> it = query.iterate(); it.hasNext();) { > Object[] result = it.next(); > Integer childId = (Integer) result[0]; > Integer grandChildCount = (Integer) result[1]; > CategoryNode childNode = childNodes.get(childId); > childNode.setHasChildren(grandChildCount != 0); > childNode.setIsLeaf(grandChildCount == 0); > } > > return new ArrayList<CategoryNode>(childNodes.values()); > } > > } > > > > public interface CategoryDao { > > public CategoryNode findById(String id); > > public List<CategoryNode> getChildren(CategoryNode node); > > public List<CategoryNode> findRoots(); > } > > > > > public class CategoryTreeModelAdapter implements > TreeModelAdapter<CategoryNode> { > > private HibernateCategoryDao hibernateCategoryDao; > > public CategoryTreeModelAdapter(HibernateCategoryDao > hibernateCategoryDao) { > this.hibernateCategoryDao = hibernateCategoryDao; > } > > public List<CategoryNode> getChildren(CategoryNode node) { > return hibernateCategoryDao.getChildren(node); > } > > public boolean isLeaf(CategoryNode node) { > return node.isLeaf(); > } > > public boolean hasChildren(CategoryNode node) { > return node.hasChildren(); > } > > public String getLabel(CategoryNode node) { > return node.getCategory().getLabel(); > } > } > > > > public class Tree { > > @Inject > private Session session; > > private HibernateCategoryDao hibernateCategoryDao; > > void setupRender() { > hibernateCategoryDao = new HibernateCategoryDao(session); > } > > public TreeModel getModel() { > return getTreeModel(); > } > > private TreeModel<CategoryNode> treeModel; > > public TreeSelectionModel getSelectModel(){ > return new DefaultTreeSelectionModel(); > } > > public TreeModel<CategoryNode> getTreeModel() { > if (treeModel == null) { > ValueEncoder<CategoryNode> encoder = new > ValueEncoder<CategoryNode>() { > > @Override > public String toClient(CategoryNode node) { > return node.getCategory().getId().toString(); > } > > @Override > public CategoryNode toValue(String node) { > return hibernateCategoryDao.findById(node); > } > }; > > treeModel = new DefaultTreeModel<CategoryNode>(encoder, new > CategoryTreeModelAdapter(hibernateCategoryDao), > hibernateCategoryDao.findRoots()); > } > return treeModel; > } > } > > > Tree.tml > t:tree t:model="model" t:selectionModel="selectModel"/> > > > -- > View this message in context: http://tapestry.1045711.n5.nabble.com/Tapestry-TreeGrid-tp5462126p5488350.html > Sent from the Tapestry - User mailing list archive at Nabble.com.