我有一个关于休眠和排序条款的问题。我有一个包含 3 个表的 mySQL 数据库:A、B 和 C。与这些表对应的 Java 代码如下。
A类代码:
package database;
import java.util.Set;
public class A implements java.io.Serializable {
private Integer id;
private Set<B> listB;
public A() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Set<B> getListB() {
return listB;
}
public void setListB(Set<B> listB) {
this.listB = listB;
}
}
B类代码:
package database;
public class B implements java.io.Serializable {
private Integer id;
private A a;
private C c;
public B() {
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
public C getC() {
return c;
}
public void setC(C c) {
this.c = c;
}
}
C类代码:
package database;
public class C implements java.io.Serializable {
private Integer id;
private int num;
public C() {
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public int getNum() {
return this.num;
}
public void setNum(int num) {
this.num = num;
}
}
相关的 .hbm 文件在这里
表A映射:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="database">
<class name="A" table="A">
<id
column="id"
name="Id"
type="integer"
>
<generator class="increment" />
</id>
<set name="listB" cascade="all, delete-orphan" inverse="true" lazy="true" fetch="select" order-by="c.Id asc">
<key column="a_id"/>
<one-to-many class="B"/>
</set>
</class>
</hibernate-mapping>
表 B 映射:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="database">
<class name="B" table="B">
<id
column="id"
name="Id"
type="integer"
>
<generator class="increment" />
</id>
<many-to-one name="a" class="A" fetch="select">
<column name="a_id" not-null="true" />
</many-to-one>
<many-to-one name="c" class="C" fetch="select">
<column name="c_id" not-null="true" />
</many-to-one>
</class>
</hibernate-mapping>
表 C 映射:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="database">
<class name="C" table="C">
<id
name="Id"
type="integer"
column="id"
>
<generator class="increment"/>
</id>
<property
name="Num"
column="num"
type="integer"
not-null="true"
length="10"
/>
</class>
</hibernate-mapping>
我的问题是关于 A.hbm 文件中的“order-by”子句。我想订购的不是 c.Id,而是 c.Num
<set name="listB" cascade="all, delete-orphan" inverse="true" lazy="true" fetch="select" order-by="c.Num asc">
不幸的是,当我这样做时,我得到以下异常:
Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not initialize a collection: [database.A.listB#1]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.loader.Loader.loadCollection(Loader.java:2069)
at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:62)
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:628)
at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:83)
at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1853)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:366)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:186)
at Test.main(Test.java:36)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'listb0_.c.Num' in 'order clause'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4120)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4052)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2503)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2664)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2815)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2322)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1849)
at org.hibernate.loader.Loader.doQuery(Loader.java:718)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:270)
at org.hibernate.loader.Loader.loadCollection(Loader.java:2062)
... 8 more
我是hibernate的新手,我读了一些关于标准的东西可以帮助我,但我不知道如何将它们用于hbm文件。
感谢您的帮助,
劳里安
在尝试了你给我的想法之后,我仍然没有答案。首先,我编写了以下方法将数据输入数据库:
private static void create() {
A a = new A();
HibernateUtil.save(a);
C c1 = new C();
c1.setNum(5);
HibernateUtil.save(c1);
C c2 = new C();
c2.setNum(2);
HibernateUtil.save(c2);
C c3 = new C();
c3.setNum(7);
HibernateUtil.save(c3);
C c4 = new C();
c4.setNum(3);
HibernateUtil.save(c4);
B b1 = new B();
b1.setA(a);
b1.setC(c1);
HibernateUtil.save(b1);
B b2 = new B();
b2.setA(a);
b2.setC(c4);
HibernateUtil.save(b2);
B b3 = new B();
b3.setA(a);
b3.setC(c3);
HibernateUtil.save(b3);
B b4 = new B();
b4.setA(a);
b4.setC(c2);
HibernateUtil.save(b4);
A a2 = new A();
HibernateUtil.save(a2);
C c5 = new C();
c5.setNum(13);
HibernateUtil.save(c5);
C c6 = new C();
c6.setNum(11);
HibernateUtil.save(c6);
C c7 = new C();
c7.setNum(10);
HibernateUtil.save(c7);
C c8 = new C();
c8.setNum(14);
HibernateUtil.save(c8);
B b5 = new B();
b5.setA(a2);
b5.setC(c5);
HibernateUtil.save(b5);
B b6 = new B();
b6.setA(a2);
b6.setC(c8);
HibernateUtil.save(b6);
B b7 = new B();
b7.setA(a2);
b7.setC(c7);
HibernateUtil.save(b7);
B b8 = new B();
b8.setA(a2);
b8.setC(c6);
HibernateUtil.save(b8);
}
它给了我 2 个 A 实例,每个都有一个包含 4 个 B 实例的列表。
然后,我尝试了这段代码:
Criteria crit = HibernateUtil.currentSession().createCriteria(A.class);
Criteria critb = crit.createCriteria("listB");
Criteria critc = critb.createCriteria("c");
critc.addOrder(Order.asc("num"));
List<A> list = critc.list();
// Code to iterate over listA
for (A a : list) {
List<B> listB = a.getListB();
for (B b : listB) {
System.out.print(b.getC().getNum() + ", ");
}
System.out.println();
}
我获得的列表包含 A 的每个实例的 4 次,输出为:
2, 7, 3, 5,
2, 7, 3, 5,
2, 7, 3, 5,
2, 7, 3, 5,
14, 13, 10, 11,
14, 13, 10, 11,
14, 13, 10, 11,
14, 13, 10, 11,
因此,我尝试将 A 类中 listB 的 getter 更改为:
public List<B> getListB() {
Criteria crit =
HibernateUtil.currentSession().createCriteria(B.class);
Criteria critc = crit.createCriteria("c");
critc.addOrder(Order.asc("num"));
return critc.list();
}
并运行以下代码:
List<A> list = (List<A>) HibernateUtil.getList("from A");
for (A a : list) {
List<B> listB = a.getListB();
for (B b : listB) {
System.out.print(b.getC().getNum() + ", ");
}
System.out.println();
}
输出是:
2, 3, 5, 7, 10, 11, 13, 14,
2, 3, 5, 7, 10, 11, 13, 14,
B 的实例引用 A 的一个或另一个实例之间没有区别,我不明白它是如何工作的......
谢谢你的帮助,
劳里安