Spring JPA Entity Graph и Self Reference происходят N + 1 запрос - PullRequest
1 голос
/ 24 апреля 2019

Я пытался использовать граф сущностей, чтобы избежать запроса N + 1, и он работал, как и ожидалось.
Он отличается от объекта самоссылки, хотя этот код может получить правильный список, возник запрос N + 1.

Мой вопрос состоит в том, как исключить N + 1 запрос с самоссылочным объектом?

Заранее спасибо.

лог и код следующим образом

Hibernate: 
    select
        sysperm0_.pval as pval1_0_0_,
        children1_.pval as pval1_0_1_,
        sysperm2_.pval as pval1_0_2_,
        sysperm0_.parent as parent4_0_0_,
        sysperm0_.created as created2_0_0_,
        sysperm0_.leaf as leaf3_0_0_,
        sysperm0_.pname as pname5_0_0_,
        sysperm0_.ptype as ptype6_0_0_,
        sysperm0_.updated as updated7_0_0_,
        children1_.parent as parent4_0_1_,
        children1_.created as created2_0_1_,
        children1_.leaf as leaf3_0_1_,
        children1_.pname as pname5_0_1_,
        children1_.ptype as ptype6_0_1_,
        children1_.updated as updated7_0_1_,
        children1_.parent as parent4_0_0__,
        children1_.pval as pval1_0_0__,
        sysperm2_.parent as parent4_0_2_,
        sysperm2_.created as created2_0_2_,
        sysperm2_.leaf as leaf3_0_2_,
        sysperm2_.pname as pname5_0_2_,
        sysperm2_.ptype as ptype6_0_2_,
        sysperm2_.updated as updated7_0_2_ 
    from
        sys_perm sysperm0_ 
    left outer join
        sys_perm children1_ 
            on sysperm0_.pval=children1_.parent 
    left outer join
        sys_perm sysperm2_ 
            on children1_.parent=sysperm2_.pval 
    where
        sysperm0_.pval=?


Hibernate: 
    select
        children0_.parent as parent4_0_0_,
        children0_.pval as pval1_0_0_,
        children0_.pval as pval1_0_1_,
        children0_.parent as parent4_0_1_,
        children0_.created as created2_0_1_,
        children0_.leaf as leaf3_0_1_,
        children0_.pname as pname5_0_1_,
        children0_.ptype as ptype6_0_1_,
        children0_.updated as updated7_0_1_ 
    from
        sys_perm children0_ 
    where
        children0_.parent=?

    .......XN

    492373 nanoseconds spent acquiring 1 JDBC connections;
    0 nanoseconds spent releasing 0 JDBC connections;
    5197227 nanoseconds spent preparing 8 JDBC statements;
    18997333 nanoseconds spent executing 8 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    0 nanoseconds spent performing 0 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
    0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections)

сущность

@Table(name="sys_perm")
@Entity
@NamedEntityGraph(
    name = "test",
    attributeNodes = {
        @NamedAttributeNode(value="children",subgraph="sub_perm"),
    },
    subgraphs = {
        @NamedSubgraph(
            name = "sub_perm",
            attributeNodes = {
                @NamedAttributeNode("_parent")
        }
    )
  }
)
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class SysPerm implements Serializable {

    @Id
    private String pval;
    private String parent;
    private String pname;
    private Integer ptype;
    private Boolean leaf;
    @CreationTimestamp
    private Date created;
    @UpdateTimestamp
    private Date updated;

    @ManyToOne(fetch=FetchType.LAZY, cascade={CascadeType.ALL})
    @JoinColumn(name = "parent", referencedColumnName = "pval", insertable=false, updatable=false)
    @JsonIgnore
    private SysPerm _parent;

    @OneToMany(mappedBy="_parent", fetch=FetchType.EAGER, cascade={CascadeType.ALL})
    private List<SysPerm> children = new ArrayList<>();
}

хранилище

public interface SysPermRepository extends JpaRepository<SysPerm, Long>{
    @EntityGraph(value = "test", type = EntityGraphType.FETCH)
    List<SysPerm> findByPval(String pval);
}

схема

CREATE TABLE `sys_perm` (
  `pval` varchar(50) NOT NULL ,
  `parent` varchar(25) DEFAULT NULL ,
  `pname` varchar(50) DEFAULT NULL ,
  `ptype` int(3) DEFAULT NULL ,
  `leaf` tinyint(1) DEFAULT NULL ,
  `created` timestamp NULL DEFAULT NULL ,
  `updated` timestamp NULL DEFAULT NULL ,
  PRIMARY KEY (`pval`),
  UNIQUE KEY `pval` (`pval`),
  KEY `FKaiy87e3krvn4suwleaooces17` (`parent`),
  CONSTRAINT `FKaiy87e3krvn4suwleaooces17` FOREIGN KEY (`parent`) REFERENCES `sys_perm` (`pval`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
...