2014-07-07 70 views
2

從Java Persistence with Hibernate(Manning,2007)p。 419:Hibernate session.persist()vs JPA entityManager.persist()

我應該在Session上使用persist()嗎?休眠會話接口 還具有persist()方法。它具有與JPA的persist()操作相同的語義。但是,兩次操作之間在沖洗方面存在重要的差異 。在 同步,一個Hibernate的Session不級聯堅持() 操作關聯的實體和集合,即使你映射 使用此選項的關聯。 當你調用persist()時,它只能級聯到 可訪問的實體!如果使用會話API,則僅在flush-time級聯級聯()(和update())爲 。然而,在JPA 應用程序中,反過來說:只有在沖洗時級聯的persist()是 。

這樣一個難以辨認的措辭......這是什麼意思「當您調用persist()」時可到達的實體?

如果我更新相關的實體那麼豈不是「可達」?

而且...如果它是session.persist()的行爲的一部分,那麼它爲什麼不是在javadoc

+0

可達=您可以從傳遞的對象導航到持續到其他對象。這個導航是通過普通的java對象字段。可達也意味着從對象A,到對象B,到對象C等導航。 –

回答

0

我真誠地不知道如果這是真的還是假的,但我至少可以解釋這意味着什麼。

假設你有以下實體:

public class Order { 
    @OneToMany(cascade = PERSIST) 
    private List<OrderLine> lines; 
    // ... 
} 

,你做到以下幾點:

Order order = new Order(); 
session.persist(order); 
OrderLine line = new OrderLine(); 
order.addLine(line); 
session.flush(); // the flush could also be called implicitely, when committing or executing a query 

根據你的問題的文本,該行不會持久,因爲它不是從persist(order)被調用時的訂單可以獲得:此時,該行尚未處於訂單狀態。

在另一方面,是您使用實體管理器:

Order order = new Order(); 
em.persist(order); 
OrderLine line = new OrderLine(); 
order.addLine(line); 
em.flush(); // the flush could also be called implicitely, when committing or executing a query 

那麼該行會繼續存在,因爲它是從沖洗時間順序,當實體的狀態同步到到達數據庫。

+0

您的意思是'order.addLine(line)'?我想你是說這在理論上可能意味着什麼,但你不知道他們是否真的這麼做?你描述的這個場景需要每個持久化對象有多個快照...... Hibernate實際上是爲了矯枉過正嗎? – rapt

+0

是的,對不起,我的意思是'order.addLine()'。我不明白「每個持久對象的多個快照」是什麼意思。每個會話每個給定的持久對象只有一個實例。 –

0

的Hibernate的EntityManager的實現是:

org\hibernate\hibernate-entitymanager\4.3.5.Final\hibernate-entitymanager-4.3.5.Final-sources.jar!\org\hibernate\jpa\spi\AbstractEntityManagerImpl.java 

,這是堅持()方法

@Override 
public void persist(Object entity) { 
    checkOpen(); 
    try { 
     internalGetSession().persist(entity); 
    } 
    catch (MappingException e) { 
     throw convert(new IllegalArgumentException(e.getMessage())) ; 
    } 
    catch (RuntimeException e) { 
     throw convert(e); 
    } 
} 

所以JPA留存(實體)實際上是調用org.hibernate.internal.Session。堅持(實體)。

所以,不應該有JPA之間的差異,當談到堅持實體休眠。

它只能級聯到當您呼叫 persist()時可到達的實體!

2007年,Hibernate 3.2已經發布,3.3版本已經上市。當時JPA was only a draft

您也可以使用persist()而不是save(),並使用EJB3>>> early draft中定義的語義。

但是根據文檔:

如果父對象被persist(),所有的孩子都傳遞給 堅持()

對於JPA是有道理的級聯persist(),因爲根本沒有save()操作。但是當時人們使用save(),saveOrUpadet(),甚至saveOrUpdateCopy(),這些已被棄用,而不贊成使用persist()和merge()。

當時,持久的JPA定義只是一個草案,所以特定的實現並不反映明確的特徵。

+0

你是說「[Hibernate]只能級聯到當你調用persist()時可以訪問[與cascade =」persist「映射並且]在Hibernate的當前版本中不再成立的實體嗎?而且,如果在不久之前,這實際上是Hibernate的行爲,它是如何實現的(請參閱我對JB Nizet的評論)? – rapt

+0

這不是我要說的。我說在持久化方面jpa和hibernate應該沒有什麼區別。 –

+0

爲什麼它不會暗示我說的是什麼?你說:「對於JPA來說,在調用persist()時......儘管在調用persist()時....即使對於在flush()時可到達的子實體級聯也是有意義的,這意味着Hibernate現在的行爲相同。 .. – rapt