java - 在 ManyToOne 关系中触发 HQL

标签 java hibernate orm

我有具有 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;
    }

}

学生表中有一个大学的外键。

如果我想获取特定大学的所有学生,那么在 native SQL 中我可以使用以下查询来实现:

Select * from student where collegeId=1

是否可以通过从学生实体而不是大学实体中进行选择来实现与 HQL 相同的效果。

我的实用程序类:

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

最佳答案

尝试一下(刚刚在 your other question 中看到映射没问题)

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

编辑

关于您的评论,Hibernate 有一个“功能”,如果它找不到具有给定名称的字段,它只会将您提供的任何内容传递给 SQL。在你的情况下,这意味着

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

由于collegeId不是Student中的字段,因此它将按原样传递到SQL中,从而得到您想要的查询。当然,缺点是代码与底层数据库模型的耦合,绕过了 ORM 映射。

关于java - 在 ManyToOne 关系中触发 HQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27526625/

相关文章:

java - JedisPoolConfig 参数 *blockWhenExhausted* 的使用

java - 关于OpenDDR中的displayWidth和displayHeight

java - Hibernate 检索多行并存储在对象数组中

hibernate - 刷新后调用 Hibernate PostInsertEventListener

java - 从两个不同的类登录 xml 的正确方法是什么?现在我在生成的 xml 中遇到错误

java - 我可以为任何方法抛出 FileNotFoundException,还是仅针对 main 方法?

spring - 为 JpaTransactionManager 启用日志记录

java - 对于 java 开发者来说,有什么比 Hibernate 更好的呢?

java - 如何让 EclipseLink 创建 MySQL InnoDB 表?

java - 只读模式下不允许写操作 (FlushMode.MANUAL)