【问题标题】:unexpected JPA results意外的 JPA 结果
【发布时间】:2011-04-17 05:47:09
【问题描述】:

我正在学习 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 建议,我将数据打印到服务器日志以删除 测试仪界面。

    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

【问题讨论】:

    标签: orm jpa join jpql


    【解决方案1】:

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

    怎么样:

    SELECT DISTINCT c 
    FROM College c JOIN FETCH c.students
    

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

    【讨论】:

    • 感谢 Pascal 的回复,我已经完成了上述操作,它只是完成查询的大学部分,换句话说,它没有获取部分。
    • @Jon 我建议激活 SQL 日志记录以查看到底发生了什么,但我 100% 确定此查询也确实获取了学生(即你得到了一个加载了学生的学院)。
    • @Pascal 我添加了 sql 日志记录,并将我的结果添加到上述查询中。谢谢
    • @Jon 所以我们可以看到,学生们被获取了(如果你放了一个断点,college.students 应该被加载)。现在,问题是:您如何准确地进行 XML 序列化?
    • @Pascal 很好地通过 Glassfish 测试器接口(您可以在其中调用 WSDL 方法)调用它,该接口生成一个肥皂请求并返回响应。所以我并没有真正做任何事情。你想让我发布我的方法调用吗?
    猜你喜欢
    • 2013-04-26
    • 2011-09-15
    • 2012-04-02
    • 2019-05-14
    • 2017-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多