Ho una domanda sull'ibernazione e sulla clausola order-by. Ho un database mySQL contenente 3 tabelle: A, B e C. Il codice Java corrispondente a queste tabelle è qui di seguito.Clausola order-by complessa in file hibernate .hbm
Classe A Codice:
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;
}
}
Codice classe 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;
}
}
Codice classe 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;
}
}
I file .hbm associati sono qui
Tabella A mappatura:
<?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>
Tabella B mappatura:
<?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>
Tabella C mappatura:
<?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>
La mia domanda riguarda il "order-by" clausola nel file A.hbm. Vorrei ordinare non aver seguito c.Id, ma c.Num
<set name="listB" cascade="all, delete-orphan" inverse="true" lazy="true" fetch="select" order-by="c.Num asc">
Purtroppo, quando lo faccio, ottengo la seguente eccezione:
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
Sono nuovo di letargo, ho letto alcune cose sui criteri che potrebbero aiutarmi, ma non vedo come usarli in file hbm.
Grazie per l'aiuto,
Lauriane
Dopo aver provato le idee che mi hai dato, io ancora non ho la risposta. In primo luogo, ho scritto il seguente metodo per inserire i dati nel database:
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);
}
Mi dà 2 istanze di A, ognuno con una lista di 4 istanze di B.
Poi, ho provato questo codice:
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();
}
L'elenco ottengo contiene 4 volte ogni istanza di A, e il risultato è:
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,
Così ho cercato di cambiare il getter elencoB nella classe a, a:
public List<B> getListB() {
Criteria crit =
HibernateUtil.currentSession().createCriteria(B.class);
Criteria critc = crit.createCriteria("c");
critc.addOrder(Order.asc("num"));
return critc.list();
}
ed eseguire il seguente codice:
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();
}
e la produzione ammontava:
2, 3, 5, 7, 10, 11, 13, 14,
2, 3, 5, 7, 10, 11, 13, 14,
Non c'è differenza fatta tra le istanze di B riferendosi ad una o l'altra istanza di A, e non vedo come potrebbe funzionare .. .
Grazie per il vostro aiuto,
Lauriane
penso che potrebbe essere utile se si guarda e si pubblica lo sql generato da Hibernate. – Carsten