2014-09-02 219 views
2

我正在使用JPA 2.1(EclipseLink 2.5.1)和JBoss 7.1。@ManyToOne(fetch = FetchType.LAZY)延遲加載不起作用

我已經定義很簡單的JPA實體:

@Entity 
@Table(name="APLICACIONES_TB") 
public class Aplicacion implements Serializable { 

    @Id 
    @Column(name="COD_APLICACION_V") 
    private long codAplicacionV; 

    @Column(name="APLICACION_V") 
    private String aplicacionV; 

    @OneToMany(mappedBy="aplicacion") 
    private Collection<Prestacion> prestaciones; 

    ... getters and setters 
} 

@Entity 
@Table(name="PRESTACIONES_TB") 
public class Prestacion implements Serializable { 

    @Id 
    @Column(name="COD_PRESTACIONES_V") 
    private String codPrestacionesV; 

    @Column(name="DESCRIPCION_V") 
    private String descripcionV; 

    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name = "COD_APLICACION_V")  
    private Aplicacion aplicacion; 

    ... getters and setters ... 
} 

我已經開發出一種staless EJB執行一個查詢來獲取一些「Aplicacion」的實體。

@Stateless 
@LocalBean 
public class DocuEJB implements DocuEJBLocal 
{ 
    @PersistenceContext(name="DocuEjb", type=PersistenceContextType.TRANSACTION) 
    private EntityManager em; 

    public Prestacion getResult(String name) 
    { 
    return em.createNamedQuery("ExampleQueryName", Prestacion.class).getSingleResult(); 
    } 
} 

因爲我與JSF 2.1 EJB工作被注入託管bean:

@ManagedBean(name = "ManagedBean") 
@RequestScoped 
public class ManagedBean 
{ 
    @EJB DocuEJB docuEjb; 

    public String doSomething() 
    { 
    Prestacion entity = docuEjb.getResult("egesr"); 

    if (entity != null) 
    { 
     // It should return null because 'entity' should be detached 
     Aplicacion app = entity.getAplicacion(); 

     // but 'app' entity is not null, ¿why not? 
     System.out.println (app.getCodAplicacionV()); 
    } 
    } 
} 

延遲加載甚至沒有工作時延遲加載已經爲「aplicacion」字段定義'Prestacion'實體。之前發佈的,應在下一行返回一個NullPointerException異常代碼:

System.out.println (app.getCodAplicacionV()); 

,因爲「應用」實體分離,並延遲加載已配置。

爲什麼不工作延遲加載?

感謝

+2

嘗試在doSomething() – Xstian 2014-09-02 18:08:28

+2

上添加@Transactional如果在分離的對象中調用getAplicacion(),則應該引發臭名昭着的LazyInitializationException。這不是......所以應用程序依然存在。 – 2014-09-02 22:04:09

+0

@ Xstian - 我已經嘗試了你的建議(事務持久化上下文),但我得到了同樣的結果。 – Eduardo 2014-09-03 06:20:24

回答

0

嘗試添加@Transactional上DoSomething的(),我認爲你的事務管理器不能很好地配置。

你可以看到here官方的spring文檔。無論如何,你能否添加你的彈簧配置,以便我們能夠更好地幫助你。 :)

+0

當你說@交易,你的意思是@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)註釋? doSomething是一種EJB方法 – Eduardo 2014-09-03 08:34:08

+0

我的想法是,當您嘗試獲取關係時,事務處於關閉狀態。我建議你像SpringTransaction一樣的行爲。 – Xstian 2014-09-03 08:42:59

0

我不認爲你的行爲遭遇異常或你的問題應清楚地說明它:

  • EJB是通過默認的事務
  • 你的JSF注入的EJB,與@EJB,和我猜測JBoss可以創建一個java引用而不是代理
  • 實體正在被管理,因爲事務沒有完成,它將在doSomething結束時完成。

然後將您的實體加載到EntityManager中,並且由於存在上下文,因此延遲加載會起作用。

你會打電話em.evict(entity)與你的結果越來越,這可能會失敗,因爲實體將不再被管理。

+0

我同意你的意見。但是如果你看看我發佈的代碼,那麼一旦'doSomething'方法結束,懶惰引用就會被解析。由於這個原因,它不應該解決懶惰的參考。 – Eduardo 2014-09-03 08:39:14

+0

例如,它在哪裏不應該被加載? (因爲你的例子指向'doSomething',而不是你使用它的真實場所)。 。 – NoDataFound 2014-09-03 09:16:54

+0

對不起,你說得對,我解釋不好。 'getResult'方法是一種EJB方法,因爲爲EJB定義的持久化上下文類型是Transactional,所以'getResult'方法返回的實體應該被分離。另一方面,'doSomething'方法是一個託管bean方法,我認爲JEE容器不管理託管bean方法的事務。 – Eduardo 2014-09-03 09:25:47