Search code examples
javajodd

Jodd DbOomQuery hint with collection


I'm using Jodd DbOom to manage my queries and it's really awesome. But right now I'm are facing an undocumented situation.

I have a query that returns a list of objects(A), and each A has a list of objects (B), and each B is joined with other objects(C, D, E, etc). The problem is that the class JoinHintResolver doesn't set the values C, D, E on the B objects. The B objects are set correctly on the A objects.

Below is a test method to reproduce the error. The other used classes(Girl, BadBoy) are from Jodd test packages.

public void testHintsList() {
    Room room = new Room();
    Girl girl = new Girl();
    BadBoy badBoy = new BadBoy();
    Object[] data = new Object[] { room, badBoy, girl };

    JoinHintResolver jhr = new JoinHintResolver();
    Object[] result = jhr.join(data, "room, room.boys, room.boys.girl");
    assertEquals(1, result.length);
    assertTrue(result[0] instanceof Room);
    room = (Room) result[0];
    badBoy = room.getBoys().get(0);
    assertEquals(girl, badBoy.girl);
}

public class Room {
    private Long id;
    private List<BadBoy> boys;

    public Room() {
    }

    public Long getId() {
    return id;
    }

    public void setId(Long id) {
    this.id = id;
    }

    public List<BadBoy> getBoys() {
    return boys;
    }

    public void setBoys(List<BadBoy> boys) {
    this.boys = boys;
    }
}

The documentation doesn't have any example like this, and Google neither. So I don't know if I did something wrong, or if Jodd wasn't prepared for this situation.

How could I set the hints so that Jodd would set the values correctly?


Solution

  • So the problem here is the fact that you have a collection of BadBoys in your Room. And the hint:

    room.boys.girl
    

    suggest they you want to inject a Girl instance into a collection. In java words, this is equivalent to:

    getRoom().getBoys().setGirl(girl);
    

    Obviously, since getBoys() returns a List, we can not set the girl property.

    To test this what I've said, use the following hint instead:

    room.boys[0].girl
    

    This would inject the girl instance into the very first element of the list. Or, you can change your Room to have just a Boy property, instead of the list, and the original hint will work.

    I hope this works for you :)

    (see test)

    EDIT

    In this branch I have something that looks like a fix :) Now you can write something like:

    select $C{room.*}, $C{room.boys:boy.*}, $C{room.boys.girl:girl.*}
        from $T{Room room} join $T{Boy4 boy} on $room.id=$boy.roomId 
        join $T{Girl4 girl} on $boy.id=$girl.boyId 
        order by $room.id, $boy.id
    

    And you can have the following model:

    Room has list of Boy. Each Boy has one Girl assigned. When entityAware is on, this should work. Maybe you have time to test the branch?