Just taking another look I can see a couple of issues.

1. Are categoryId and parentCategoryId long's? If so, findById() should
take a long (not a string). If they are strings, the query should use
setString() instead of setLong(). Something has to change ;)

2. getChildren() should use Restrictions.eq("parentCategoryId",
note.getCategory().getId())

3. CategoryTreeModelAdapter should reference the interface of the DAO, not
the concrete type.

4. In your page, you probably don't need a variable to store the TreeModel
(the getter should be sufficient).

5. As I said earlier, the DAO might be better off being declared in the
Tapestry IOC registry. This would mean it's a singleton and can be
@Inject'ed. I'd do this after getting everything else working.

Once you have a working example, please post it back to the list. I think
this sounds like a prime candidate for adding to JumpStart (
http://jumpstart.doublenegative.com.au)

On Thursday, 16 February 2012, Lance Java <lance.j...@googlemail.com> wrote:
> 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<Categor

Reply via email to