1

我正在学习 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 测试器界面调用)

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

任何帮助提示或指示都会非常感谢

- - - - - - - - - - - - - - 附加信息 - - - - - - - - - - - ---------

所以我按照 Pascal 的建议执行了 SQL 日志记录,在调用该方法时会生成

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 建议我将数据打印到服务器log 以切出 Tester 界面。

    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
4

1 回答 1

1

您当前的查询正在执行 INNER JOIN,因此当两个表中至少有一个匹配项时返回行。换句话说,你会得到College每个Student都有 a 的College(这解释了为什么你在这里得到 4 倍的伯恩茅斯)。

关于什么:

SELECT DISTINCT c 
FROM College c JOIN FETCH c.students

这将返回不同College的拥有Student(并获取关联)。

于 2010-09-26T00:14:41.990 回答