hibernate 普通欄位消極式載入無效的解決辦法,hibernate欄位
關聯對象的消極式載入就不說了,大家都知道。
關於普通欄位的消極式載入,尤其是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.
而bytecode instrumentation的介紹可以參考http://www.correlsense.com/blog/java-bytecode-instrumentation-an-introduction/,本文不多作介紹。
正是因為我們的persistent classes沒有使用bytecode instrumentation增強,才導致了普通欄位無法消極式載入。
因此要改寫一下。以下為一個使用了bytecode instrumentation的持久類:
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;} }
關鍵在於FieldHandled介面和lob欄位的getter
hibernate消極式載入問題
Hibernate.initialize(stu.getCourses());
需要在SESSION關閉前。而過濾器實質上也是在SESSION前。
樓主可以再開一個SESSION,然後根據拿到的課程集合查詢課程。
hibernate問題消極式載入問題
在web.xml中配置OpenSessionInView過濾器即可解決
<!-- OpenSessionInView 配置,解決Hibernate消極式載入的問題 -->
<filter>
<filter-name>lazyLoadingFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>lazyLoadingFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>