2014-07-11 148 views
0

我對hibernate或JAXB並不特別熟悉,所以請原諒我,如果我沒有很好地解釋我的問題。Hibernate和JAXB註釋衝突

我正在使用的程序已經設置了一類hibernate實體。我的工作是添加JAXB註釋以將變量編組到XML文件。

@OneToMany(fetch = FetchType.LAZY, mappedBy = "Blah") 
@XmlElementWrapper(name = "ListOfThings") 
@XmlElement(name = "Thing") 
private Set<Stuff> stuff = new HashSet<Stuff>(0); 

當我嘗試運行該程序,我得到這個錯誤:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: package.class, no session or session was closed

我有3個變量,我使用@XmlElement批註與兩個也有@OneToMany批註。 @OneToMany變量都給我提供了同樣的錯誤,但是當它們都是臨時變量時,程序可以非常好地用非@ OneToMany註釋變量編譯。

任何想法我的問題可能是什麼?

回答

1

當JAXB寫入XML時,它遍歷包括所有關係的整個數據結構。 Hibernate使用延遲加載。當您使用JAXB創建XML時,您需要確保您的實體附加到活動的hibernate會話。這允許hibernate按照JAXB要求的那樣執行所需的查詢來填充數據結構的延遲加載部分。

0

有兩種解決方案,可以結合使用,以便對編組有最好的控制。

  • 提供一個AccessorFactory,它將創建一個自定義的Accessor。在這個訪問,您覆蓋

public abstract ValueT get(BeanT bean) throws AccessorException;

,如果POJO沒有初始化,返回null:

if (!Hibernate.isInitialized(valueT)) { return null; }

注意有一個惱人的優化方法:

public Accessor<BeanT,ValueT> optimize(@Nullable JAXBContextImpl context) { return this; }

其中c取代您的自定義訪問器,取決於您覆蓋的訪問器(請參閱FieldReflection)。

不要忘記的JAXBContext以下初始化:

HashMap<String, Object> props = new HashMap<String, Object>(); props.put(JAXBRIContext.XMLACCESSORFACTORY_SUPPORT, true); JAXBContext jaxbContext = JAXBContext.newInstance(new Class[] { clazz }, props);

  • 的第二個解決方案是重寫JAXB的AnnotationReader,這樣你可以回到你想要的註解,這取決於類, Field等等...所以如果你不想讓你的對象被編組,你可以返回XmlTransient註解。 也就是這樣做的方式:

HashMap<String, Object> props = new HashMap<String, Object>(); props.put(JAXBRIContext.ANNOTATION_READER, new CustomAnnotationReader()); JAXBContext jaxbContext = JAXBContext.newInstance(new Class[] { clazz }, props);

RuntimeInlineAnnotationReader是終局的,不能被覆寫...所以你必須複製代碼。

我personnaly結合這兩個批准,以便根據對象的上下文和內容修改編組。