我有大学和学生实体有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;
}
}
学生表中有大学的外键。
如果我想从一个特定的大学中取出所有学生,那么在原生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)
答案 0 :(得分:1)
尝试使用此功能(只需在your other question中看到映射正常)
String queryString = "select s from Student s where s.college.collegeId = 1";
修改强>
关于你的评论,Hibernate有一个&#34;功能&#34;如果它找不到具有给定名称的字段,那么无论你给它什么,它都会传递给SQL。在你的情况下,它意味着
String queryString = "from Student where collegeId=1";
由于collegeId
不是Student
中的字段,它将按原样传递给SQL,从而产生您想要的查询。当然,缺点是将代码耦合到底层数据库模型,绕过ORM映射。