2009-07-17 24 views
15

Có rất nhiều người có thể tìm thấy về googling này một chút nhưng tôi đã không hoàn toàn tìm thấy một giải pháp khả thi cho vấn đề này.Nhẹ nhàng tải một chiếc áo choàng trong hibernate

Về cơ bản những gì tôi có là một CLOB lớn trên một lớp cụ thể mà tôi muốn tải theo yêu cầu. Cách ngây thơ để làm điều này sẽ là:

class MyType { 

    // ... 

    @Basic(fetch=FetchType.LAZY) 
    @Lob 
    public String getBlob() { 
    return blob; 
    } 
} 

Điều đó không làm việc, mặc dù rõ ràng là do thực tế tôi đang sử dụng trình điều khiển oracle, ví dụ: đối tượng Lob không được đối xử như xử lý đơn giản nhưng luôn nạp. Hoặc vì vậy tôi đã được dẫn dắt để tin rằng từ sự đột nhập của tôi. Có một giải pháp sử dụng thiết bị đặc biệt để tải thuộc tính lười biếng, nhưng vì các tài liệu Hibernate dường như cho thấy chúng ít quan tâm đến việc làm việc đó một cách chính xác, vì vậy tôi không muốn đi tuyến đường đó. Đặc biệt là phải chạy thêm một biên dịch và tất cả.

Vì vậy, giải pháp tiếp theo mà tôi đã hình dung là tách đối tượng này thành một loại khác và xác định liên kết. Thật không may, trong khi các tài liệu cung cấp thông tin xung đột, rõ ràng với tôi rằng tải chậm không hoạt động trên các liên kết OneToOne với khóa chính được chia sẻ. Tôi đã đặt một mặt của liên kết là ManyToOne, nhưng tôi không chắc chắn làm thế nào để làm điều này khi có một khóa chính được chia sẻ.

Vậy ai cũng có thể đề xuất cách tốt nhất để giải quyết vấn đề này?

+0

Bạn có thể làm rõ tại sao nó không hoạt động với Oracle? – skaffman

+0

Tôi ăn thịt một chút, tôi không hoàn toàn chắc chắn vấn đề chính xác là gì (bit mơ hồ về chi tiết). Nếu vấn đề là với việc lập bản đồ, bạn có thể đưa ra một vấn đề mà lười biếng có nên tải đúng không? – wds

+0

Nếu bạn đã thử nó với Oracle, và nó không thành công, làm thế nào nó đã thất bại? – skaffman

Trả lời

5

Theo this chỉ PostgreSQL triển khai Blob thực sự lười. Vì vậy, giải pháp tốt nhất là di chuyển blob sang một bảng khác. Bạn có phải sử dụng khóa chính được chia sẻ không? Tại sao bạn không làm điều gì đó như thế này:

public class MyBlobWrapper { 
    @Id 
    public Long getId() { 
     return id; 
    } 
    @Lob 
    public String getBlob() { 
     return blob; 
    } 
    @OneToOne(fetch=FetchType.LAZY,optional=false) 
    public MyClass getParent() { 
     return parent; 
    } 
} 
+0

Blob chỉ là một trường trong cùng một bảng để có, phải sử dụng khóa chính được chia sẻ. Cách tiếp cận của bạn hoạt động miễn là tùy chọn = "false" được đặt ở bên sở hữu. Tôi giả định rằng sẽ phá vỡ khủng khiếp khi đối tượng là null? – wds

+0

D'oh. Tất nhiên nó sẽ không bao giờ là null khi khóa chính tồn tại. Nó sẽ chỉ là lĩnh vực clob đó là null. Bit của một thinko ở đó, cảm ơn. :-) – wds

+0

Đây là bản đồ cần thiết trên btw phụ huynh (MyType). bạn có thể muốn bao gồm nó trong câu trả lời của bạn: @OneToOne (fetch = FetchType.LAZY, optional = false) – wds

4

Thay vì làm equilibristics với các chú thích ngủ đông, người ta có thể chỉ cần cố gắng chuyển đổi lĩnh vực này từ String vào Clob (hoặc Blob):

@Lob 
@Basic(fetch=FetchType.LAZY) 
@Column(name = "FIELD_COLUMN") 
public Clob getFieldClob() { 
    return fieldClob; 
} 

public void setFieldClob(Clob fieldClob) { 
    this.fieldClob = fieldClob; 
} 

@Transient 
public String getField() 
{ 
    if (this.getFieldClob()==null){ 
    return null; 
    } 
    try { 
    return MyOwnUtils.readStream(this.getFieldClob().getCharacterStream()); 
    } catch (Exception e) { 
    e.printStackTrace(); 
    } 

    return null; 
} 

public void setField(String field) 
{ 
    this.fieldClob = Hibernate.createClob(field); 
} 

Làm việc cho tôi (lĩnh vực bắt đầu tải lazily, trên Oracle).

+0

điều này làm cho trường được nạp lazily? Từ những gì tôi có thể nói điều này chỉ cần thêm tiện lợi getter/setter để truy cập lob như một chuỗi? –

+0

@BenGeorge Lưu ý rằng chú thích Lob đang được đặt trên trình thu thập Clob trong câu trả lời của tôi, trái ngược với một chuỗi getter trong câu hỏi. Và tôi không sử dụng trường Clob trực tiếp, nhưng chỉ thông qua một bộ thu hồi tạm thời. Cảnh báo: phiên bản Hibernate mà tôi đã thử, nếu tôi nhớ chính xác, 3.2. Để xác minh rằng tải thực sự là lười biếng, tôi đã sử dụng Wireshark để kiểm tra lưu lượng truy cập đến/từ cơ sở dữ liệu. –

3

Vì bạn dường như đang sử dụng Hibernate Tôi tự hỏi, nếu vấn đề của bạn có liên quan đến tính năng Hibernate sau:

Using Lazy Properties Fetching

Hibernate3 hỗ trợ quyến rũ lười biếng tài sản cá nhân. Kỹ thuật tối ưu hóa này còn được gọi là tìm nạp nhóm. Xin lưu ý rằng đây chủ yếu là một tính năng tiếp thị; tối ưu hóa hàng đọc là nhiều hơn nữa quan trọng hơn tối ưu hóa đọc cột. Tuy nhiên, chỉ tải một số thuộc tính của một lớp học có thể hữu ích trong trường hợp cực đoan. Ví dụ: , khi các bảng cũ có hàng trăm cột và dữ liệu không thể cải thiện được.

Tải tài sản lười biếng yêu cầu công cụ bytecode xây dựng. Nếu các lớp kiên trì của bạn không được nâng cao, Hibernate sẽ bỏ qua cài đặt thuộc tính lười biếng và quay lại tìm nạp ngay lập tức.

Xem Bytecode Instrumentation for Hibernate Using Maven.

0

Bài đăng cũ, nhưng chỉ có một người đã giúp tôi, nhờ câu trả lời @TadeuszKopec.

Có vẻ như khó làm việc tải blob lười biếng với JPA. Tôi đã thử liên kết @OneToOne, nhưng nó phức tạp hơn giúp đỡ. Tôi chỉ chuyển các byte đến lớp khác, không có tổ chức nào với MyClass (mẹ Cùng bảng, cùng id.):

@Entity 
@Table(name="MyTable") 
public class MyBlobWrapper{ 

    @Id 
    @Column(name = "id") // id of MyTable, same as MyClass 
    private Long id; 

    @Lob 
    private byte[] bytes; 
} 

@Entity 
@Table(name="MyTable") 
public class MyClass{ 

    @Id 
    @Column(name = "id") 
    private Long id; 
    // other fields ..... 
} 

Chỉ cần nhớ để tuôn ra cha mẹ, trước khi lưu blob:

em.persist(parent); 
em.flush(); 
em.merge(new MyBlobWrapper(parent_id,new byte[1000])); 

Bây giờ tôi có thể tải bản pdf một mình:

String query1 = " select PDF from MyBlobWrapper PDF where PDF.id = :id"; 

Tôi chỉ là người mới bắt đầu với JPA, hy vọng điều đó sẽ hữu ích.

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