5

hibernate と order-by 句について質問があります。A、B、C の 3 つのテーブルを含む mySQL データベースがあります。これらのテーブルに対応する 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

私は冬眠するのが初めてです。私を助けることができる基準についていくつか読んでいますが、それらを 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);
}

A のインスタンスが 2 つあり、それぞれに B の 4 つのインスタンスのリストがあります。

次に、このコードを試しました:

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 のゲッターを次のように変更しようとしました。

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, 

A のいずれかのインスタンスを参照する B のインスタンス間に違いはなく、どのように機能するかわかりません...

ご協力いただきありがとうございます、

ローリアン

4

1 に答える 1

4

C クラス マッピングのプロパティ名 "Num" を "num" に修正してください。

  1. A の Order By 句

    • A は C に直接接続されていないため、A から C に順序を設定することはできません。
    • c.id で機能した理由は、B に列 c_id (C クラス マッピング) が含まれており、order by 句がテーブル B の c_id 列に適用され、C の id 列には適用されないためです。
    • c.num を設定すると、hibernate はテーブル B にない列を検索しようとします。
  2. 条件クエリ

    • 基準クエリを使用するには、最初に A から order-by 句を削除するか、有効なものを使用します
    • 基準クエリは、Java コードで「セッション」を使用して作成され、hbm ファイルで構成されません。

サンプルコード

Criteria crit = session.createCriteria(A.class);
Criteria critb = crit.createCriteria("listB");
Criteria critc = critb.createCriteria("c");
critc.addOrder(Order.asc("num"));
List<A> listA = critc.list();
// Code to iterate over listA

A.java

// remove listB and add following
private Set<C> listC;
// Add getters/setters

A のマッピング

// remove listB mapping and add following
<set name="listC" table="b" fetch="select" inverse="true">
    <key column="a_id"/>
    <many-to-many column="c_id" unique="true" class="C" order-by="num asc" />
</set>

Java コード

Criteria crit = session.createCriteria(A.class);
List<A> listA = crit.setFetchMode("listC", FetchMode.JOIN).list();
// iterate or use listA

唯一の欠点は、B を個別に管理できないことです。B から列「id」を削除し、a_id と c_id を挿入/更新/削除操作の複合主キーとして作成する必要があります。上記の選択クエリの変更で十分です。


于 2013-06-05T06:30:42.457 に答える