意外的JPA结果

时间:2010-09-25 18:48:46

标签: orm jpa join jpql

我正在学习JPA并遇到问题。我的主要问题是当我加入我的实体并且不太明白为什么我得到结果我...而且如果有人可以帮助我真的会非常好,它真的会减慢我的进度。

实体来说

学院

@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;
    }
}

学生

@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;
        }
    }

好的,所以我的目标是查询所有大学并返回与他们相关的所有学生。 我期待我的命名查询

SELECT col FROM College col JOIN col.students s

我的回答是(通过glassfish Tester界面调用)

    <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>

因为你可以想象这个大学只在数据库中存在一次,但我知道这个大学实体有四个学生(我猜它为什么重复)。 解决方案我和希望的那种东西(如sudo xml类似的方式)

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

任何帮助提示或指示都将得到很好的回应 感谢

---------------------------其他信息------------------ ------------

所以我执行了SQL日志记录,就像Pascal在调用方法genorate

时提出的那样
SELECT DISTINCT t1.ID, t1.NAME, t0.ID, t0.NAME, t0.college_Id FROM STUDENT t0, COLLEGE t1 WHERE (t0.college_Id = t1.ID)

我还在我的数据库中测试了上面的脚本,结果就像我希望JPA返回一样。

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

所以我想这意味着我的JPA设置一定存在问题? 因为它显然没有正确地重新包装结果。

再次感谢

-----------更新--------------------------- 进一步从Pascals建议我将数据打印到服务器日志以切断 测试人员界面。

    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;
 }

结果是应该的,但这仍然没有反映在Glassfish界面中。

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

1 个答案:

答案 0 :(得分:1)

您当前的查询正在执行INNER JOIN,因此当两个表中至少有一个匹配时返回行。换句话说,你会得到每个College Student College的{​​{1}}(这解释了为什么你得到 Bournemouth 的4倍)。

怎么样:

SELECT DISTINCT c 
FROM College c JOIN FETCH c.students

这会返回College Student {{1>} {和获取关联。)