2013-05-30 25 views
5

Tôi có câu hỏi về mệnh đề ngủ đông và theo thứ tự. Tôi có một cơ sở dữ liệu mySQL chứa 3 bảng: A, B và C. Mã Java tương ứng với các bảng đó là sau đây.Điều khoản theo thứ tự phức tạp thành các tệp .hbm hibernate

Class A mã:

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; 
    } 

} 

Mã lớp 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; 
    } 
} 

Mã lớp 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; 
    } 
} 

Các tập tin .hbm liên quan đang ở đây

Bảng A ánh xạ:

<?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ảng B lập bản đồ:

<?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> 

Bảng C lập bản đồ:

<?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> 

Câu hỏi của tôi là về "lệnh bằng cách" điều khoản trong file A.hbm. Tôi muốn đặt hàng không sau c.Id, nhưng c.Num

<set name="listB" cascade="all, delete-orphan" inverse="true" lazy="true" fetch="select" order-by="c.Num asc"> 

Thật không may, khi tôi làm như vậy, tôi nhận được ngoại lệ sau đây:

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 

Tôi mới vào ngủ đông, tôi đọc một số điều về tiêu chí có thể giúp tôi, nhưng tôi không thấy cách sử dụng chúng thành các tệp hbm.

Cảm ơn vì đã giúp,

Lauriane

Sau khi thử các ý tưởng mà bạn đã cho tôi, tôi vẫn không có câu trả lời. Trước tiên, tôi đã viết phương pháp sau để nhập dữ liệu vào cơ sở dữ liệu:

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); 
} 

Nó cung cấp cho tôi 2 trường hợp A, mỗi trường có danh sách 4 trường hợp B.

Sau đó, tôi đã cố gắng mã này:

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(); 
    } 

Danh sách tôi có được chứa 4 lần mỗi trường hợp của A, và đầu ra là:

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, 

Vì vậy, tôi đã cố gắng để thay đổi getter của listB trong lớp 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(); 
} 

và chạy đoạn mã sau:

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(); 

    } 

Và kết quả là:

2, 3, 5, 7, 10, 11, 13, 14, 
2, 3, 5, 7, 10, 11, 13, 14, 

Không có sự khác biệt giữa các trường hợp B kh¶o một hoặc các trường hợp còn lại của A, và tôi không thấy làm thế nào nó có thể làm việc .. .

Nhờ sự giúp đỡ của bạn,

Lauriane

+0

Tôi nghĩ rằng nó có thể có ích nếu bạn xem và đăng sql được tạo bởi Hibernate. – Carsten

Trả lời

4

tên thuộc tính Vui lòng đúng "Num" thành "num" để lập bản đồ lớp C.

  1. Sắp xếp theo khoản A

    • Bạn sẽ không thể để thiết lập trật tự trên C từ A, như A không được kết nối trực tiếp đến C.
    • Lý do tại sao nó làm việc cho c .id là vì B chứa cột c_id (ánh xạ lớp C) và mệnh đề theo thứ tự được áp dụng trên cột c_id trên bảng B và không phải cột id trên C
    • Khi bạn đặt c.num, hibernate sẽ cố gắng tra cứu cột trong bảng B mà chúng ta không có.
  2. Tiêu chuẩn Query

    • Để sử dụng tiêu chí truy vấn đầu tiên loại bỏ lệnh quy định tại khoản từ A hoặc sử dụng hợp lệ một trong Tiêu chuẩn truy vấn
    • là được tạo ra sử dụng "phiên" trong mã java và không được được định cấu hình trong tệp hbm.

Mẫu mã

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 

Mapping cho 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 Mã

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

Hạn chế duy nhất là B không thể được quản lý một cách độc lập và bạn cần phải loại bỏ cột "id" từ B và làm a_id và c_id làm khóa chính kết hợp cho thao tác chèn/cập nhật/xóa, cho truy vấn chọn ở trên thay đổi là đủ.


+0

Thực tế là tôi không hiểu. Tôi phải viết mã Tiêu chí ở đâu? Nếu tôi viết nó vào phương thức "getListB()" của A, tôi nhận được tất cả các trường hợp B, ngay cả những trường hợp không được liên kết với A. Nếu không, nếu tôi viết nó trước khi nhận được một thể hiện của A, không có thứ tự. – user2436719

+0

bạn phải viết ví dụ trong lớp DAO – nachokk