2014-11-24 79 views
0

這裏是我的代碼片段:如何獲得休眠層次懶惰對象

public class Object1 implements Serializable { 
    @Id 
    @Column(length = 36) 
    protected String id; 

    @Column(length = 36, insertable = false, updatable = false) 
    protected String parentID; 

    @OneToMany(fetch = FetchType.LAZY) 
    @JoinColumn(name = "object2ID", referencedColumnName = "parentID") 
    protected List<Object2> parents = new ArrayList<>(); 

    public List<Object2> getParents() { 
     return parents; 
    } 
} 

public class Object2 implements Serializable { 
    @Id 
    @Column(length = 36) 
    protected String id; 

    @Column(length = 36, insertable = false, updatable = false) 
    protected String object2ID; 

    @Column(length = 36, insertable = false, updatable = false) 
    protected String parentID; 

    @OneToMany(fetch = FetchType.LAZY) 
    @JoinColumn(name = "object2ID", referencedColumnName = "parentID") 
    protected List<Object2> parents = new ArrayList<>(); 

    public List<Object2> getParents() { 
     return parents; 
    } 
} 

與應用類:

public class Application { 
    public static Logger logger = LoggerFactory.getLogger(Application.class); 

    public static void main(String[] args) { 
     Path HIBERNATE_CONFIGURATION = Paths.get(""); 
     Configuration configuration = new Configuration().configure(HIBERNATE_CONFIGURATION.toFile()); 
     ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
       configuration.getProperties()).build(); 
     SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry); 

     Session session = sessionFactory.openSession(); 
     Object1 object1 = (Object1) session.get(Object1.class, "1"); 
     logger.info(object1.toString()); 

     Object2 object2 = object1.getParents().get(0); 
     logger.info(object2.toString()); 

     while (!object2.getParents().isEmpty()) { 
      object2 = object2.getParents().get(0); 
      logger.info(object2.toString()); 
     } 

     session.close(); 
    } 

} 

我越來越Object1符合市場預期,但對象2拋出異常org.hibernate.LazyInitializationException: could not initialize proxy - no Session

會話未關閉,爲什麼我收到此錯誤?

我使用Hibernate的核心:4.3.7.Final

解決:

嗨。謝謝大家。我發現解決我的問題。我試圖得到OneToMany,但在數據庫引用中的實數是ManyToMany類型。我爲db和model創建了一個小的改變。

我重命名對象。 這裏是新的代碼片段:

@Entity 
@Table(name = "Houses") 
public class House implements Serializable { 
    @Id 
    @Column(length = 36) 
    protected String id; 

    @Column(length = 36) 
    protected String parentGUID; 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "parentguid", referencedColumnName = "guid") 
    protected AddressObject address; 

    public AddressObject getAddress() { 
     return address; 
    } 

    @Override 
    public String toString() { 
     return "Object1{" + 
       "id='" + id + '\'' + 
       ", parentGUID='" + parentGUID + '\'' + 
       '}'; 
    } 
} 

@Entity 
@Table(name = "AddressObjects") 
public class AddressObject implements Serializable { 
    @Id 
    @Column(length = 36) 
    protected String id; 

    @Column(length = 36, unique = true) 
    protected String guid; 

    @Column(length = 36, nullable = true) 
    protected String parentGUID; 

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "address") 
    protected List<House> houses = new ArrayList<>(); 

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "upHierarchicObject") 
    protected List<AddressObject> downHierarchicObject = new ArrayList<>(); 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "parentguid", referencedColumnName = "guid") 
    protected AddressObject upHierarchicObject; 

    public List<House> getHouses() { 
     return houses; 
    } 

    public List<AddressObject> getDownHierarchicObject() { 
     return downHierarchicObject; 
    } 

    public AddressObject getUpHierarchicObject() { 
     return upHierarchicObject; 
    } 

    @Override 
    public String toString() { 
     return "Object2{" + 
       "id='" + id + '\'' + 
       ", guid='" + guid + '\'' + 
       ", parentGUID='" + parentGUID + '\'' + 
       '}'; 
    } 
} 

與應用類:

public class Application { 
    public static Logger logger = LoggerFactory.getLogger(Application.class); 

    public static void main(String[] args) { 
     ArrayList<Object> objects = new ArrayList<>(); 
     Path HIBERNATE_CONFIGURATION = Paths.get("config/hibernate.test.cfg.xml"); 
     Configuration configuration = new Configuration().configure(HIBERNATE_CONFIGURATION.toFile()); 
     ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
       configuration.getProperties()).build(); 
     SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry); 

     Session session = sessionFactory.openSession(); 
     House house = (House) session.get(House.class, "1"); 
     objects.add(house); 

     AddressObject addressObject = house.getAddress(); 
     objects.add(addressObject); 

     while (addressObject.getUpHierarchicObject() != null) { 
      addressObject = addressObject.getUpHierarchicObject(); 
      objects.add(addressObject); 
     } 

     for (Object obj : objects) { 
      logger.info("Object: {}", obj); 
     } 
     session.close(); 
    } 
} 

但是,我不爲什麼我除了LazyInitializationException中。這是休眠的錯誤?

+2

你必須創建一個事務,以及... – 2014-11-24 10:25:25

+0

如果我加入交易,即不工作 – ArtOfShine 2014-11-24 13:14:18

+0

我沒有看到你的代碼進行任何交易。你也會遇到一個無限循環,因爲'object2.getParents()。get(0)'不會從集合中刪除元素,因此無限運行。 – 2014-11-24 13:42:46

回答

0

懶惰是當你忘記在查詢中進行讀取(此處爲父項),並且在關閉會話後嘗試檢索java對象 在這部分代碼中,你如何知道object2的來臨從object1中獲取父項? 這裏我們只是測試空

object1.getParents() != null 

但在慵懶的情況下,如果你想使用它的對象不爲空,但虛擬

,你需要有會話打開 但在這步驟會話已經關閉 因爲我們關閉會話只是從數據庫retriving對象之後

例子:

Session s = sessions.openSession(); 
Transaction tx = s.beginTransaction(); 

Employee e = (Employee) s.createQuery("from Employee e where e.name=:empName").setString("empName", eName).uniqueResult(); 
List roles = u.getRoles(); 
tx.commit(); 
s.close(); 
String role = roles.get(0); // This line will throw error 

Easy Solution 

Use lazy=false in your Entity class. 

注意

這裏未關閉會話。這可能做的伎倆

提取條件可以做的伎倆取指=「加入」在很多一對一的實體類條件FetchMode.JOIN 在映射中定義的抓取策略的影響:

retrieval via get() 

希望這有助於。

+0

當會話仍然打開時,OP會看到異常*。那麼這是如何發生的? – JimmyB 2014-11-25 08:16:37

+0

調整提取策略可以在多對一的條件下執行trick fetch =「join」 映射中定義的提取策略影響: 通過get() – techGaurdian 2014-11-25 08:44:45

+0

檢索@ArtOfShine:問題是否解決? – techGaurdian 2014-11-26 08:21:57

-1

你必須提供虛擬循環,第一次提取的所有對象。

例如

for (Object2 obj:object1.getParents()) { 
      obj.getName(); 
} 
+0

我更新問題。增加解決。 – ArtOfShine 2014-11-26 09:25:59