首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >.hbm hibernate文件中的复杂order-by子句

.hbm hibernate文件中的复杂order-by子句
EN

Stack Overflow用户
提问于 2013-05-30 21:59:27
回答 1查看 9.2K关注 0票数 5

我有一个关于hibernate和order-by子句的问题。我有一个包含3个表的mySQL数据库: A、B和C。与这些表相对应的Java代码如下。

A类代码:

代码语言:javascript
复制
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类代码:

代码语言:javascript
复制
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类代码:

代码语言:javascript
复制
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映射:

代码语言:javascript
复制
<?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映射:

代码语言:javascript
复制
<?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映射:

代码语言:javascript
复制
<?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

代码语言:javascript
复制
<set name="listB" cascade="all, delete-orphan" inverse="true" lazy="true" fetch="select" order-by="c.Num asc">

不幸的是,当我这样做时,我得到了以下异常:

代码语言:javascript
复制
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文件。

谢谢你的帮助

劳里安

在尝试了你给我的想法之后,我仍然没有答案。首先,我编写了以下方法将数据输入数据库:

代码语言:javascript
复制
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实例的列表。

然后,我尝试了以下代码:

代码语言:javascript
复制
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();
    }

我得到的列表包含4次A的每个实例,输出为:

代码语言:javascript
复制
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的获取方法更改为:

代码语言:javascript
复制
public List<B> getListB() {
             Criteria crit =
     HibernateUtil.currentSession().createCriteria(B.class);
     Criteria critc = crit.createCriteria("c");
     critc.addOrder(Order.asc("num"));
     return critc.list();
}

并运行以下代码:

代码语言:javascript
复制
 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();

    }

输出结果是:

代码语言:javascript
复制
2, 3, 5, 7, 10, 11, 13, 14, 
2, 3, 5, 7, 10, 11, 13, 14, 

B引用A的一个或另一个实例之间没有区别,我看不出它是如何工作的……

谢谢你的帮忙,

劳里安

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-06-05 14:30:42

对于C类映射,请将属性名"Num“改为"num”。

中的Order By子句

代码语言:javascript
复制
- You will not be able to set order on C from A, as A is not directly connected to C.
- The reason why it worked for c.id is because B contains column c\_id (C class mapping) and order by clause is applied on c\_id column on table B and not id column on C
- When you set c.num, hibernate will try to look-up column in table B which we do not have.

  1. Criteria Query

代码语言:javascript
复制
- To use criteria query first remove order-by clause from A or use valid one
- Criteria query is to be created using "session" in java code and not be configured in hbm file.

示例代码

代码语言:javascript
复制
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

  • 如果可以将b表视为中间表,在这种情况下不需要B类,并且可以使用连接表b (http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/associations.html#assoc-bidirectional-join)将A与C关联,则可以在hbm文件中使用order-by子句,如下所示:

A.java

代码语言:javascript
复制
// remove listB and add following
private Set<C> listC;
// Add getters/setters

A的映射

代码语言:javascript
复制
// 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代码

代码语言:javascript
复制
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作为insert/update/delete操作的复合主键,因为上面的select查询更改就足够了。

有关更多详细信息,请参阅:http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querycriteria.html

  • Apart from Criteria Query您可以使用hbm query:http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html

  • You也可以开始使用注释和JPA
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16838233

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档