2008-11-30 34 views
5

Tôi đã phải đối mặt với vấn đề này, các đối tượng ngủ đông trên serialization sản xuất xmls unexpect có chứa tất cả các mã nhạc cụ từ Hibernate.Vấn đề với serializing Hibernate đối tượng bằng cách sử dụng XStream

Chúng tôi đã làm sạch một số đối tượng trước khi tuần tự hóa đối tượng.

Nhưng, có tùy chọn chuẩn nào để sắp xếp trực tiếp đối tượng trực tiếp không?

+0

Có thể bạn có thể hiển thị XML trông như thế nào? –

Trả lời

3

Tôi đã không sử dụng XStream trước đây, nhưng tôi đã sắp xếp các thực thể được quản lý theo Hibernate. Nó không vui.

Có hai vấn đề lớn:

  • tải Lazy;
  • Mối quan hệ một-nhiều.

Điều trước đây là hiển nhiên - bạn cần dữ liệu thực tế để tuần tự hóa. Cái thứ hai là ít hơn - bất kỳ mối quan hệ một-nhiều nào mà bạn khai báo đối với các giao diện bộ sưu tập (ví dụ: Set<T>) sẽ được cắm vào bởi các triển khai bộ sưu tập của riêng Hibernate (unserializable!). Điều này cũng có thể là nơi các lớp học của Hibernate đang chảy máu vào các đối tượng của bạn.

tôi đã kết thúc việc viết mã phản chiếu (trên thực tế nội tâm) mà đã làm điều này:

  1. Với phiên mở, chạm vào đồ thị toàn bộ đối tượng để buộc nạp bất kỳ tổ chức bốc dỡ;
  2. Đóng phiên Hibernate (bao gồm mọi giao dịch liên quan đến kết nối của nó);
  3. Đi bộ đồ thị đối tượng, thay thế bất kỳ danh sách, bộ hoặc bản đồ nào với các thể hiện của ArrayList, HashSet hoặc HashMap (các bộ sưu tập có thể tuần tự hóa).

Lưu ý rằng bước 2 là quan trọng - nếu bạn thay thế các bộ sưu tập trước khi đóng cửa phiên giao dịch, Hibernate sẽ chỉ cần đặt các bộ sưu tập của riêng mình quay lại ngay khi gần ...

Edit: @ cliff.meyers phát hiện một chi tiết của việc thực hiện mà tôi quên đề cập đến: nếu bạn làm điều này, bạn cần giới hạn đồ thị đối tượng chỉ đi đến các thực thể của riêng bạn và xem đường dẫn tham chiếu vòng tròn (ví dụ: bằng cách lưu vào bộ nhớ đệm đối tượng bạn đã đi).

1

Có một số thông tin về vấn đề này (và mẫu mã) so với tại Codehaus JIRA:

http://jira.codehaus.org/browse/XSTR-226

Chúng tôi đã viết một số công cụ để làm việc xung quanh loại này của vấn đề đối với một loạt các triển khai Remoting khác (Axis 1, Blaze DS, v.v.) Những gì chúng tôi đã làm là rất giống với giải pháp của Dan, mặc dù chúng tôi đã bổ sung khả năng khai báo các đường dẫn đối tượng để đi và cái nào để "bắn" bởi vì trong nhiều tình huống chúng tôi không quan tâm đến tất cả dữ liệu; nó cũng sẽ dẫn đến các vấn đề nghiêm trọng với vấn đề "n + 1 lựa chọn" xảy ra hàng ngàn lần! :) Tôi nghĩ rằng việc thực hiện một bộ chuyển đổi XStream sẽ là phương pháp tối ưu vì bạn chỉ phải đi bộ đồ thị đối tượng một lần. Nếu bạn đặt FlushMode.MANUAL trên Session của bạn, bạn cũng sẽ có thể sửa đổi đồ thị đối tượng khi bạn đi mà không Hibernate làm bất cứ điều gì khó chịu. Sử dụng điều này một cách thận trọng mặc dù nó là một kỹ thuật hơi tiên tiến.

+0

Rất tiếc, hãy quên đề cập ban đầu các loại đối tượng giới hạn để đi vào (cú pháp snip của bạn) - cảm ơn chỉnh sửa ... –

1

Tôi gặp phải sự cố tương tự mặc dù Im không sử dụng chế độ ngủ đông.Tôi nhìn vào pruner enitity nhưng nó không hoàn toàn những gì tôi đang tìm kiếm như tôi đã tìm kiếm một giải pháp đơn giản hơn.

Tôi đã đưa ra một giải pháp rất đơn giản bằng cách sử dụng sự phản chiếu làm mất đi các đối tượng nâng cao của CGLIB như sự quyến rũ.

vui lòng truy cập http://www.anzaan.com/2010/06/serializing-cglib-enhanced-proxy-into-json-using-xstream/ ví dụ và mã.

3

Tôi đã đưa ra giải pháp phần nào đủ. Trong ứng dụng của tôi, chỉ PersistentSets đã làm rối tung XML được tạo ra bởi XStream. Vì vậy, tôi đã thêm một Converter để XStream (mà chạy với mở Hibernate Session và đối tượng trực tiếp):

XStream xs = new XStream(); 
xs.registerConverter(new CollectionConverter(xs.getMapper()) { 
    @Override 
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { 
     org.hibernate.collection.PersistentSet ps = (PersistentSet) source; 
     super.marshal(new HashSet(ps), writer, context); 
    } 

    @Override 
    public boolean canConvert(Class type) { 
     return type.isAssignableFrom(org.hibernate.collection.PersistentSet.class); 
    } 
}, XStream.PRIORITY_VERY_HIGH); 
String s = xs.toXML(processInstance); 

XML serialized trông giống như dưới đây:

<processLogs class="org.hibernate.collection.PersistentSet"> 
    <pl.net.bluesoft.rnd.processtool.model.ProcessInstanceLog> 
     <id>813017</id> 
     <entryDate> 
     <time>1310832421216</time> 
     <timezone>GMT</timezone> 
     </entryDate> 
     <eventI18NKey>process.log.action-performed</eventI18NKey> 
     <additionalInfo>Wydrukuj wniosek</additionalInfo> 
     <logValue>GENERATE_APPLICATION</logValue> 
     <logType>PERFORM_ACTION</logType> 
     <state reference="../../../definition/states/pl.net.bluesoft.rnd.processtool.model.config.ProcessStateConfiguration[8]"/> 
     <processInstance reference="../../.."/> 
     <user reference="../../../creator"/> 
    </pl.net.bluesoft.rnd.processtool.model.ProcessInstanceLog> 
    <pl.net.bluesoft.rnd.processtool.model.ProcessInstanceLog> 
     <id>808211</id> 
     <entryDate> 
     <time>1310828206169</time> 
     <timezone>GMT</timezone> 
     </entryDate> 
     <eventI18NKey>process.log.action-performed</eventI18NKey> 
     <additionalInfo>Zaakceptuj</additionalInfo> 
     <logValue>ACCEPT</logValue> 
     <logType>PERFORM_ACTION</logType> 
     <state reference="../../../definition/states/pl.net.bluesoft.rnd.processtool.model.config.ProcessStateConfiguration[4]"/> 
     <processInstance reference="../../.."/> 
     <user reference="../../../creator"/> 
    </pl.net.bluesoft.rnd.processtool.model.ProcessInstanceLog> 

Trong trường hợp của tôi, các thuộc tính lớp không quan trọng, vì vậy tôi đã bỏ qua giá trị của nó. Bạn có thể tinker với nó.

+0

+1 Rất hữu ích, cảm ơn! Vấn đề tiếp theo của tôi là một PersistentSet được bao bọc trong UnmodifiableSet, khó chịu, không phải là một lớp hiển thị: -/ – Rup

+0

Để ngăn chặn thuộc tính lớp, tôi nghĩ bạn cần triển khai một Mapper tùy chỉnh trả về serializedClass (PersistentSet.class) == HashSet .lớp học. Nhưng có vẻ như đó là một lượng công việc hợp lý để thiết lập. – Rup

1

đã không được sử dụng nó, nhưng xstream-for-beans có vẻ phù hợp (trích dẫn):

dự án này cung cấp thực hiện vẽ bản đồ và bộ chuyển đổi nhằm nâng cao xStream trên khía cạnh sau:

  1. đối tượng Serialize như họ được tiếp xúc bởi getters và setters. Các tính năng XStream có sẵn cho các trường sẽ làm việc cho các thuộc tính được định nghĩa cho các proprerties getter/setter.
  2. Thực hiện tuần tự hóa các đối tượng được quản lý: tự động bỏ qua các trường không liên quan và thông tin lớp học .
  3. Xử lý trường "ngoại tuyến" và đối tượng proxy.

tôi đã viết một lần tùy chỉnh XStream Converter s để đối phó với vấn đề này, như một phần của một dự án mã nguồn đóng không may. xstream-for-beans giao dịch với các vấn đề rất giống nhau, cũng có giá trị một shot.

Tôi đã sử dụng công cụ Pojoizer của Terracotta thành công trong quá khứ, nhưng tôi không nghĩ rằng nó được duy trì nữa.

Các vấn đề liên quan