JPA @Basic單表查詢?nèi)绾螌崿F(xiàn)大字段懶加載
JPA @Basic單表查詢實現(xiàn)大字段懶加載
近期看了JPA@Basic注解的使用,看到該注解可以設(shè)置字段的懶加載。
1.以前碰到的懶加載:
我們知道,多表關(guān)聯(lián)的時候,我們是可以配置懶加載的,比如一個Company類,里面可以關(guān)聯(lián)員工表,辦公設(shè)備表,當我們查看公司信息的時候,我們并不需要直接加載員工表,辦公設(shè)備表,只需要在用戶查看員工,查看設(shè)備的時候再加載,這樣可以提高加載效率。
長話短說,大概是這樣子的
@Entity @Table(name = "Company") public class Company { @OneToMany(mappedBy = "cId", fetch = FetchType.LAZY) private List<Employee> employees; // other properties //getters and setters }
2、單表大字段懶加載
對于一張表時,里面有一個存儲用戶頭像的字段,我們只需要當用戶點入用戶詳情頁的時候才去加載頭像,其余時間不用加載。例如為什么你微信換了頭像,其他人是不能在群聊中立即看到的,需要你查看用戶詳情時才會看到一樣。
寫了一個例子:
新建test表:
實體類:
@Entity @Table(name = "TEST") public class TestCMP { @Id @IdSequenceConsumer(producerClass = UUIDProducer.class) private String id; @Lob @Basic(fetch = FetchType.LAZY) private String image; private String name; //getters and setters }
repository接口:
@Repository public interface TestRepository extends CrudRepository<TestCMP,String> { }
測試方法:
@Test @Transactional(value = "nwTransactionManager") public void BasicTest3() { TestCMP testCMP = testRepository.findOne("12345"); //懶加載,image沒有查出來 System.out.println(testCMP); System.out.println(testCMP.getImage()); //主動去獲取image,進行加載 }
1、看到網(wǎng)上有同學直接設(shè)置了@Basic注解,沒有實現(xiàn)的截圖。
但我試一下,并沒有實現(xiàn)懶加載,還是一次性就加載出來了。
打出來的sql為全查,沒有實現(xiàn)懶加載:
select testcmp0_.id as id1_0_0_, testcmp0_.image as image2_0_0_, testcmp0_.name as name3_0_0_ from TEST testcmp0_ where testcmp0_.id=?
2、分析其中原因,應(yīng)是:即使我通過@Basic設(shè)置了懶加載,但有g(shù)etter,toString方法,已經(jīng)不允許它懶加載了,所以會全查。
3、讓實體類實現(xiàn)FieldHandled接口,這個接口,目的就是利用FieldInterceptorImpl這個類,他專門對懶加載的字段加了一個攔截器,能夠?qū)屑虞d的值注入到實體類中。(這類似于將懶加載的字段與原有代碼隔離開,加載的時候再寫進去,讀出來)
將實體類改為:
@Entity @Table(name = "TEST") public class TestCMP implements FieldHandled{ @Id @IdSequenceConsumer(producerClass = UUIDProducer.class) private String id; @Lob @Basic(fetch = FetchType.LAZY) private String image; private String name; @Transient @JsonIgnore private FieldHandler fieldHandler; @Override public void setFieldHandler(FieldHandler handler) { this.fieldHandler = handler; } @Override public FieldHandler getFieldHandler() { return fieldHandler; } /** * 獲取image * * @return image */ public String getImage() { if (fieldHandler != null) { return (String) fieldHandler.readObject(this, "image", this.image); } return null; } // other getters and setters }
首先查詢sql:懶加載不查詢image
select testcmp0_.id as id1_0_0_, testcmp0_.name as name3_0_0_ from TEST testcmp0_ where testcmp0_.id=?
當獲取image時sql:
select testcmp_.image as image2_0_ from TEST testcmp_ where testcmp_.id=?
打印testCMP的結(jié)果:
TestCMP@d56fc13[id=12345,image=<null>,name=jenkins, fieldHandler=FieldInterceptorImpl(entityName={路徑省略}.cmp.TestCMP,dirty=false,uninitializedFields=[image])]
注意點:
第一次查詢與加載懶加載數(shù)據(jù),應(yīng)在同一個事務(wù)中,如
如果查和加載懶加載數(shù)據(jù)在不同的方法中,可以對整個service加事務(wù)@Transactional
jpa 懶加載 、N+1、指定字段查詢示例
屬性懶加載
說明:默認情況下,實體的屬性會被立即加載(一次全部加載)。但是,我們也可以延遲加載它們。這對于存儲大量數(shù)據(jù)的列類型有用:CLOB,BLOB,VARBINARY
配置項
spring.jpa.open-in-view=false
@Basic(fetch = FetchType.LAZY)
查詢的實體類如果進行g(shù)et懶加載屬性操作,會出現(xiàn)N+1性能問題
控制字段輸出
@Entity @JsonInclude(Include.NON_EMPTY)
避免對具有空值的字段進行序列化
指定字段查詢1(接口式)
定義接口類
public class AuthorDto implements Serializable { private static final long serialVersionUID = 1L; private final String name; private final int age; public AuthorDto(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } }
repository
@Repository public interface AuthorRepository extends JpaRepository<Author, Long> { @Transactional(readOnly = true) List<AuthorDto> findByGenre(String genre); }
指定字段查詢2(構(gòu)造函數(shù)式)
定義接口類
public class AuthorDto implements Serializable { private static final long serialVersionUID = 1L; private final String name; private final int age; public AuthorDto(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } }
repository
@Repository public interface AuthorRepository extends JpaRepository<Author, Long> { @Transactional(readOnly = true) @Query(value = "SELECT new com.bookstore.dto.AuthorDto(a.name, a.age) FROM Author a") List<AuthorDto> fetchAuthors(); }
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
java中char對應(yīng)的ASCII碼的轉(zhuǎn)化操作
這篇文章主要介紹了java中char對應(yīng)的ASCII碼的轉(zhuǎn)化操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08springboot實現(xiàn)定時任務(wù)@Scheduled方式
這篇文章主要介紹了springboot實現(xiàn)定時任務(wù)@Scheduled方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07SpringBoot 設(shè)置傳入?yún)?shù)非必要的操作
這篇文章主要介紹了SpringBoot 設(shè)置傳入?yún)?shù)非必要的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02Java字節(jié)與字符流永久存儲json數(shù)據(jù)
本篇文章給大家詳細講述了Java字節(jié)與字符流永久存儲json數(shù)據(jù)的方法,以及代碼分享,有興趣的參考學習下。2018-02-02