hibernate的n+1問題已經是一個很常見的問題了。
最近遇到了很多次的n+1問題,總結一下解決辦法:
1.ManyToOne中的n+1:
當查詢單個的時候,可以使用來進行讓其join查詢,
覺得manyToOne的n+1問題同樣可以使用這種方法,其中FetchMode有三個參數:
public enum FetchMode { /** * use a select for each individual entity, collection, or join load. * 產生n+1的查詢,每個都生成一條查詢語句 * n+1條查詢 */ SELECT, /** * use an outer join to load the related entities, collections or joins. * 使用一條outer join進行查詢 * 1條查詢 */ JOIN, /** * use a subselect query to load the additional collections. * 使用一條查詢list語句進行查詢 * 2條查詢 */ SUBSELECT }
2.查詢主體為list的時候的查詢
上面的辦法應該是可以解決n+1,但是在查詢主表的列表是竟然發現還是會產生多一條語句的情況,於是經過百般查找,找到了一種通過hql來解決此問題的方法:
@Entity @Table(name = "xxxx") public class ShowInfoEntity implements Serializable { private static final long serialVersionUID = -5078958740245381213L; // id @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; // numapi @OneToOne(fetch = FetchType.EAGER, optional = false, mappedBy = "showInfo") @Fetch(FetchMode.JOIN) private ShowNumber numapi;
首先這個是主表,其中與從表ShowNumber有一個關聯關系,此關聯關系是定義在從表中的。
看到這個類上有配置@Fetch 其在查詢單個ShowInfoEntity時是能完美的起作用的,即是join查詢,但是在查詢List<ShowInfoEntity>時就沒有這么幸運了,
會先查詢一個List<ShowInfoEntity> 之后在查詢n條numapi,
使用left join語句也不能解決問題,
最后找到了left join fetch:
@Query("select t from ShowInfoEntity t LEFT join fetch t.numapi r where t.enable =0 and t.accountId in (?1) and t.timeline<?2")
List<ShowInfoEntity> findByFlush(List<Long> toUsersPredicate, Long time, Pageable page);
順便說一句,hibernate 的hql語句中的join挺麻煩的,需要先配置好關聯關系,然后join 主表.從表
列舉一下hql中的join連接
1。左外連接
左外連接(Left Outer Join)查詢出左表對應的復合條件的所有記錄
2.左外抓取連接
左外抓取連接指定在Hibernate檢索數據時,采用抓取的方式,直接將數據加載到與主表對象關聯的從表屬性中。
3.右外連接
HQL中使用關鍵字right outer join右外連接
4.內連接
內連接(Inner Join)是指兩個表中指定的關鍵字相等的值才會出現在結果集中的一種查詢方式。HQL中使用關鍵字inner join進行內連接,
5.抓取內連接