1. 程式人生 > >hibernate 普通欄位延遲載入無效的解決辦法(如:Lazy Fetch Blob)

hibernate 普通欄位延遲載入無效的解決辦法(如:Lazy Fetch Blob)

http://blog.csdn.net/dys1990/article/details/38728175

http://stackoverflow.com/questions/2605477/spring-hibernate-blob-lazy-loading

關於普通欄位的延遲載入,尤其是lob欄位,若沒有延遲載入,對效能影響極大。然而簡單的使用 @Basic(fetch = FetchType.LAZY) 註解並沒有效果。hibernate對此的解釋是Lazy property loading requires buildtime bytecode instrumentation. If your persistent classes are not enhanced, Hibernate will ignore lazy property settings and return to immediate fetching.


正是因為我們的persistent classes沒有使用bytecode instrumentation增強,才導致了普通欄位無法延遲載入。

因此要改寫一下。以下為一個使用了bytecode instrumentation的持久類: 

關鍵在於FieldHandled介面和lob欄位的getter

public class PublicSchemeTaskFile  implements java.io.Serializable , FieldHandled  {


    // Fields    

     /**
	 * 
	 */
     private static final long serialVersionUID = -8297912895820802249L;
     private Integer id;
     private PublicTask publicSchemeTask;
     private Integer fileType;
     private String fileName;
     private byte[] content;
     
     private FieldHandler fieldHandler;//用於延遲載入表字段,關聯物件延遲載入的話無需此技術
 	
 	@JSON(serialize = false)
 	public FieldHandler getFieldHandler() {
 		return fieldHandler;
 	}

 	public void setFieldHandler(FieldHandler fieldHandler) {
 		this.fieldHandler = fieldHandler;
 	}
    // Constructors

    /** default constructor */
    public PublicSchemeTaskFile() {
    }

	/** minimal constructor */
    public PublicSchemeTaskFile(Integer id) {
        this.id = id;
    }
   

   
   

	// Property accessors
    @Id 
    
    @Column(name="ID", unique=true, nullable=false, precision=22, scale=0)
    @GeneratedValue(strategy=GenerationType.SEQUENCE,generator = "PUBLIC_SCHEME_TASK_FILE_SEQ")
    public Integer getId() {
        return this.id;
    }
    
    public void setId(Integer id) {
        this.id = id;
    }
    @JSON(serialize = false)
	@ManyToOne(fetch=FetchType.LAZY)
     @JoinColumn(name="PUBLIC_TASK_ID")

    public PublicTask getPublicSchemeTask() {
        return this.publicSchemeTask;
    }
    
    public void setPublicSchemeTask(PublicTask publicSchemeTask) {
        this.publicSchemeTask = publicSchemeTask;
    }
    
    @Column(name="FILE_TYPE", precision=22, scale=0)

    public Integer getFileType() {
        return this.fileType;
    }
    
    public void setFileType(Integer fileType) {
        this.fileType = fileType;
    }
    
    @Column(name="FILE_NAME", length=50)

    public String getFileName() {
        return this.fileName;
    }
    
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }
    @JSON(serialize = false)
    @Lob
    @Basic(fetch = FetchType.LAZY) 
    @Column(name="CONTENT")

    public byte[] getContent() {
    	 if (fieldHandler != null) {
		        return (byte[]) fieldHandler.readObject(this, "content", content);
		     }
		 return null;
    }
    
    public void setContent(byte[] content) {
        this.content = content;
    }
 

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		PublicSchemeTaskFile other = (PublicSchemeTaskFile) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}
   

}

但是,僅僅是這樣,對導致需要用這個lazy fetch的欄位時,無法獲取到它的value,一直處於null 的狀態,這時候就需要用FieldHandler來處理了。

如下:

http://stackoverflow.com/questions/7902250/jpa-lazy-at-simple-byte-field-level

I've cheched it on Hibernate v.4.3.5 and JPA v.1.5.0, PostgreSQL 9.3. Worked like a charm. Example:

public class Attachment implements FieldHandled{
    @Transient
    private FieldHandler fieldHandler;
...
...
    @Lob
    @Column(name=CONTENT, nullable=false)
    @Basic(fetch = FetchType.LAZY, optional = false)
    private byte[] content;

...
...
    public byte[] getContent() {
    if(fieldHandler!=null){
        return (byte[])fieldHandler.readObject(this, "content", content);
    }
    return content;
    }

    public void setContent(byte[] content) {
    if(fieldHandler!=null){
        fieldHandler.writeObject(this, "content", this.content, content);
        return;
    }
    this.content = content;
    }

}