简体   繁体   English

在ManyToOne关系中解雇HQL

[英]Firing HQL in ManyToOne relationship

I have College and Student entities having OneToMany relationship: 我有拥有OneToMany关系的大学和学生实体:

@Entity
public class College {

    @Id
    @GeneratedValue
    private int collegeId;

    private String collegeName;

    @OneToMany

    private Collection<Student> students = new ArrayList<Student>();

    public int getCollegeId() {
        return collegeId;
    }

    public void setCollegeId(int collegeId) {
        this.collegeId = collegeId;
    }

    public String getCollegeName() {
        return collegeName;
    }

    public void setCollegeName(String collegeName) {
        this.collegeName = collegeName;
    }

    public Collection<Student> getStudents() {
        return students;
    }
    public void setStudents(Collection<Student> students) {
        this.students = students;
    }
}

@Entity
public class Student {

    @Id
    @GeneratedValue
    private int studentId;

    private String studentName;


    public int getStudentId() {
        return studentId;
    }

    public void setStudentId(int studentId) {
        this.studentId = studentId;
    }

    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }

}

There is a foreign key to college in Student table. 在学生表中有一个指向大学的外键。

If I want to fetch all students from a perticular college then in native SQL I can do tha with following query: 如果我想从一所专科学院取回所有学生,那么在本机SQL中,我可以使用以下查询进行操作:

Select * from student where collegeId=1

Is it possible to achieve same with HQL by selecting from students entities and not from college entity. 通过从学生实体而不是大学实体中进行选择,是否可以通过HQL实现相同的目标

My utility class: 我的实用程序类:

public class ManyToOne {

    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("org.hibernate.examples");

        EntityManager em = emf.createEntityManager();
        College college1 = new College();
        college1.setCollegeName("College1");


        College college2 = new College();
        college2.setCollegeName("College2");

        Student student1 = new Student();
        student1.setStudentName("std1");

        college1.getStudents().add(student1);

        Student student2 = new Student();
        student2.setStudentName("std2");

        college2.getStudents().add(student2);

        Student student3 = new Student();
        student3.setStudentName("std3");

        college1.getStudents().add(student3);

        Student student4 = new Student();
        student4.setStudentName("std4");

        college1.getStudents().add(student4);

        em.getTransaction().begin();

        em.persist(college1);
        em.persist(college2);
        em.persist(student1);
        em.persist(student2);
        em.persist(student3);
        em.persist(student4);

        em.getTransaction().commit();
        em.close();

        em = emf.createEntityManager();
        em.getTransaction().begin();

        String queryString = "select students from "+ College.class.getName()+"   where collegeId = 1";

        Query query = em.createQuery(queryString);

        List<Student> students = query.getResultList();
        for(int i=0;i<students.size();i++)
            System.out.println(students.get(i).getStudentName());
        em.getTransaction().commit();
        em.close();
        emf.close();
    }
}

Exception stacktrace: 异常stacktrace:

Exception in thread "main" java.lang.IllegalStateException: No data type for node: org.hibernate.hql.internal.ast.tree.IdentNode 
 \-[IDENT] IdentNode: 'students' {originalText=students}

    at org.hibernate.hql.internal.ast.tree.SelectClause.initializeExplicitSelectClause(SelectClause.java:174)
    at org.hibernate.hql.internal.ast.HqlSqlWalker.useSelectClause(HqlSqlWalker.java:924)
    at org.hibernate.hql.internal.ast.HqlSqlWalker.processQuery(HqlSqlWalker.java:692)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:665)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:301)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:249)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:278)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:206)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:158)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:131)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:93)
    at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:167)
    at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:301)
    at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:236)
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1800)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:328)
    at utils.ManyToOne.main(ManyToOne.java:66)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

Try with this (just saw in your other question that mappings are ok) 尝试使用此方法(在您的其他问题中就看到映射是可以的)

String queryString = "select s from Student s where s.college.collegeId = 1";

EDIT 编辑

With regard to your comment, Hibernate has a "feature" where if it can't find a field with given name, it will just pass down to SQL whatever you give it. 关于您的注释,Hibernate具有一个“功能”,如果它找不到具有给定名称的字段,则无论您提供什么名称,它都将直接传递给SQL。 In your case it means that 就您而言,这意味着

String queryString = "from Student where collegeId=1";

since collegeId is not a field in Student , it will be passed into SQL as it is, resulting in the query you want. 由于collegeId不是Student的字段,它将按原样传递到SQL中,从而生成您想要的查询。 Of course, the downside is coupling of your code to underlying DB model, bypassing ORM mappings. 当然,缺点是绕过ORM映射将代码耦合到基础数据库模型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM