hibernate 普通字段延迟加载无效的解决办法(如:Lazy Fetch Blob)

来源:互联网 发布:迪卡侬 天猫 知乎 编辑:程序博客网 时间:2024/06/05 03:13

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;    } @Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + ((id == null) ? 0 : id.hashCode());return result;}@Overridepublic 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

The trick how to achive this described in this topic: http://justonjava.blogspot.it/2010/09/lazy-one-to-one-and-one-to-many.html

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;    }}







0 0