tags:

views:

52

answers:

1

Hi, Im learning JPA and having problems. My main problem is when i join my entitys and dont quite understand why im getting the results i am .. and its realy slowing my progress if someone could help i would be very greatful.

Entitys

College

@Entity
@NamedQueries({
    @NamedQuery(name=College.allCollegeQuery,query="SELECT col FROM College col"),
    @NamedQuery(name=College.collegeStudentJoinQuery,query="SELECT DISTINCT col FROM College col JOIN FETCH col.students"),
    @NamedQuery(name=College.collegeStudentBasicJoinQuery,query="SELECT col FROM College col JOIN col.students s")
})
public class College {

    public static final String allCollegeQuery = "allCollegeQuery";
    public static final String collegeStudentJoinQuery = "collegeStudentJoinQuery";
    public static final String collegeStudentBasicJoinQuery = "collegeStudentBasicJoinQuery";

    @Id
    @GeneratedValue
    private long id;
    private String name;

    @OneToMany(mappedBy="college")
    private List<Student> students;

    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public List<Student> getStudents() {
        return students;
    }
}

Student

@Entity
@NamedQueries({
    @NamedQuery(name=Student.allStudentsQuery, query="SELECT stu FROM Student stu"),
    @NamedQuery(name=Student.studentsCollageQuery, query="SELECT stu.college FROM Student stu WHERE stu.id = :id"),
    @NamedQuery(name=Student.studentsWithCollageIDQuery, query="SELECT stu FROM Student stu WHERE stu.college.id = :id")
})
public class Student {

    public static final String allStudentsQuery = "allStudentsquery";
    public static final String studentsCollageQuery = "studentsCollageQuery";
    public static final String studentsWithCollageIDQuery = "studentsCollagewithIDQuery";

    @Id
    @GeneratedValue
    private long id;
    private String name;

    @ManyToOne
    private College college;

    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public College getCollege() {
        return college;
    }
    @XmlTransient
        public void setCollege(College college) {
            this.college = college;
        }
    }

Ok so my goal is to query all college's and to return all the students related to them. Which i was expecting my named query to do

SELECT col FROM College col JOIN col.students s

My responce was (invoked via glassfish Tester interface)

    <return>
        <id>1</id>
        <name>"Bournemouth</name>
    </return>
    <return>
        <id>1</id>
        <name>"Bournemouth</name>
    </return>
    <return>
        <id>1</id>
        <name>"Bournemouth</name>
    </return>
    <return>
        <id>1</id>
        <name>"Bournemouth</name>
    </return>

As you can imagen this college only exists once in the database, but i know there are four students attached to this college entity (which i guess why it has repeated). The solution i and kind of hoping for would be somthing like (in a sudo xml kind way)

<return>
   <id>1</id>
   <name>Bournemouth</name>
   <students>
     <student>
     </student>
    </students>
</return>

any help tips or pointers would be greatfuly recived Thanks

--------------------------- Additional Info ------------------------------

So i performed the SQL logging as Pascal kindly suggested which upon calling the method genorates

SELECT DISTINCT t1.ID, t1.NAME, t0.ID, t0.NAME, t0.college_Id FROM STUDENT t0, COLLEGE t1 WHERE (t0.college_Id = t1.ID)

I also tested the above script in my DB and its results are as i would expect JPA to return.

ID    name              id       name     col_id 
1   "Bournemouth    2   James   1
1   "Bournemouth    3   Rich    1
1   "Bournemouth    1   Jon 1
1   "Bournemouth    4   tom 1

so i guess this means there must be a problem in my JPA setup? as its obviously not repacking the results correctly.

Thanks Again

----------- Update --------------------------- Further from Pascals suggestions i printed the data to the server log to cut out the Tester interface.

    public List<College> getCollageWithStudents(){
    List<College> s = null;
    try{
        Query query = em.createNamedQuery(College.collegeStudentBasicJoinQuery);
        s = query.getResultList();

        for (int i = 0; i < s.size(); i++) {
                College c = (College) s.get(i);
                System.out.println("College "+c.getId() + "  "+c.getName());
                System.out.println("Amt Students: "+c.getStudents().size());
                for (int j = 0; j < c.getStudents().size(); j++) {
                    Student stu = (Student) c.getStudents().get(j);
                    System.out.println(stu.getId() + "  "+stu.getName());
                }
            }
    }catch (Exception e) { 
        System.out.println(e.toString());
    }
    return s;
 }

The result are as the should be but this is still not reflected in the Glassfish interface.

INFO: College 1  "Bournemouth
INFO: Amt Students: 4
INFO: 2  James
INFO: 3  Rich
INFO: 1  Jon
INFO: 4  tom
+1  A: 

Your current query is doing an INNER JOIN and thus returns rows when there is at least one match in both tables. In other words, you'll get the College of each Student that has a College (and this explains why you are getting 4 times the the Bournemouth here).

What about:

SELECT DISTINCT c 
FROM College c JOIN FETCH c.students

That would return distinct College having Student (and fetch the association).

Pascal Thivent
Thanks for the responce Pascal, i have treid the above it only seams to be completing College part of the query, in other words its not doing to fetch part.
Jon
@Jon I suggest activating SQL logging to see what is happening exactly but I'm 100% sure this query does fetch the students too (i.e. you get a College with its Students loaded).
Pascal Thivent
@Pascal i have added sql logging with my results added to the above query. Thanks
Jon
@Jon So as we can see, the students are fetched (and the `college.students` should be loaded if you put a breakpoint). Now, the question is: how are you doing the XML serialization exactly?
Pascal Thivent
@Pascal well its being called throught the Glassfish tester interface (where you can call WSDL methods) which genorates a soap request and returns the responce. So im not realy doing anything presonaly. would you like me to post my method call?
Jon
@Jon Oh, yes, right, I forgot you were using the Tester interface. What do you get when bypassing the web service layer?
Pascal Thivent
@Pascal sorry i dont follow you? what would you like me to do? thanks for keeping with me
Jon
@Jon I meant doing a direct Java call, not through the tester interface. From my point of view, the query is correct, the returned result should be correct. I just don't know where the glitch is introduced so I propose to not use the tester interface for now.
Pascal Thivent
@Pascal i have updated the above and we have some results. It would appear that for some reason the tester interface does parse the soap responce correctly. Do you know of somthing i can use as an alternative to test my web services localy? Thanks for your help
Jon
@Jon Maybe your IDE offers some similar feature (AFAIK, Eclipse and NetBeans do). But it's a weird issue.
Pascal Thivent