Hibernate HQL连接获取不是递归获取 [英] Hibernate HQL join fetch not recursively fetching

查看:115
本文介绍了Hibernate HQL连接获取不是递归获取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下查询和方法

  private static final String FIND =SELECT DISTINCT domain FROM Domain domain LEFT OUTER JOIN FETCH domain.operators LEFT OUTER JOIN FETCH domain.networkCodes WHERE domain.domainId =:domainId; 

@Override
public Domain find(Long domainId){
Query query = getCurrentSession()。createQuery(FIND);
query.setLong(domainId,domainId);
return(Domain)query.uniqueResult();

Domain as

  @Entity 
@Table
public class Domain {
@Id
@GenericGenerator(name =generator,strategy =increment)
@GeneratedValue(generator =generator)
@Column(name =domain_id)
private long domainId;

@Column(nullable = false,unique = true)
@NotNull
私有字符串名称;

@Column(nullable = false)
@NotNull
@Enumerated(EnumType.STRING)
private DomainType type;

@OneToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
},fetch = FetchType.EAGER)
@JoinTable(joinColumns = {
@JoinColumn(name =domain_id)
},inverseJoinColumns = {
@JoinColumn(name =code)
})
@NotEmpty
@Valid //需要重现,因为我们在创建域时指定了网络代码
private Set< NetworkCode> networkCodes = new HashSet<>();

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(joinColumns = {
@JoinColumn(name =parent,referencedColumnName =domain_id)
},inverseJoinColumns = {
@JoinColumn(name =child,referencedColumnName =domain_id)
})
private Set< Domain> operators = new HashSet<>();
// more
}

我希望这个单个查询能够获取设置< NetworkCode> 设置< Domain >关系,但不是。假设 Domain I查询有两个运算符,Hibernate会执行1 + 2 * 2 = 5个查询



<$ p $ Hibernate:选择不同的domain0_.domain_id为domain1_1_0_,domain2_.domain_id为domain1_1_1_,networkcod4_.code为code2_2_,domain0_.name为name1_0_,domain0_.type为type1_0_,domain2_.name为name1_1_,domain2_。键入为type1_1_,operators1_.parent作为parent1_0__,operators1_.child作为child4_0__,networkcod3_.domain_id作为domain1_1_1__,networkcod3_.code作为code5_1__来自域domain0_左外部连接domain_operators operators1_ on domain0_.domain_id = operators1_.parent left外部连接域domain2_ on operators1_ .child = domain2_.domain_id内部连接domain_network_codes networkcod3_ on domain0_.domain_id = networkcod3_.domain_id内部连接network_code networkcod4_ on networkcod3_.code = networkcod4_.code where domain0_.domain_id =?
Hibernate:选择operators0_.parent作为parent1_1_​​,operators0_.child作为child4_1_,domain1_.domain_id作为domain1_1_0_,domain1_.name作为name1_0_,domain1_.type作为类型1_0_来自domain_operators操作员0_内部连接领域domain1_ on operators0_.child = domain1_。 domain_id其中operators0_.parent =?
Hibernate:选择networkcod0_.domain_id as domain1_1_1_,networkcod0_.code as code5_1_,networkcod1_.code as code2_0_ from domain_network_codes networkcod0_ inner join network_code networkcod1_ on networkcod0_.code = networkcod1_.code where networkcod0_.domain_id =?
Hibernate:选择operators0_.parent作为parent1_1_​​,operators0_.child作为child4_1_,domain1_.domain_id作为domain1_1_0_,domain1_.name作为name1_0_,domain1_.type作为类型1_0_来自domain_operators操作员0_内部连接领域domain1_ on operators0_.child = domain1_。 domain_id其中operators0_.parent =?
Hibernate:选择networkcod0_.domain_id as domain1_1_1_,networkcod0_.code as code5_1_,networkcod1_.code as code2_0_ from domain_network_codes networkcod0_ inner join network_code networkcod1_ on networkcod0_.code = networkcod1_.code where networkcod0_.domain_id =?

我猜这是因为我加入了元素,但他们必须联合起来。有没有一个HQL查询我可以执行,将做到这两个?

解决方案

如果您知道您的树中只有两个级别,你有没有想过加入更深的一个层次。

  SELECT DISTINCT domain FROM Domain domain 
LEFT OUTER JOIN FETCH domain.operators operators1
LEFT OUTER JOIN FETCH domain.networkCodes
LEFT OUTER JOIN FETCH operators1.operators operators2
LEFT OUTER JOIN FETCH operators1.networkCodes
WHERE domain.domainId =:domainId


I have the following query and method

private static final String FIND = "SELECT DISTINCT domain FROM Domain domain LEFT OUTER JOIN FETCH domain.operators LEFT OUTER JOIN FETCH domain.networkCodes WHERE domain.domainId = :domainId";

@Override
public Domain find(Long domainId) {
    Query query = getCurrentSession().createQuery(FIND);
    query.setLong("domainId", domainId);
    return (Domain) query.uniqueResult();
}

With Domain as

@Entity
@Table
public class Domain {
    @Id
    @GenericGenerator(name = "generator", strategy = "increment")
    @GeneratedValue(generator = "generator")
    @Column(name = "domain_id")
    private Long domainId;

    @Column(nullable = false, unique = true)
    @NotNull
    private String name;

    @Column(nullable = false)
    @NotNull
    @Enumerated(EnumType.STRING)
    private DomainType type;

    @OneToMany(cascade = {
            CascadeType.PERSIST,
            CascadeType.MERGE
    }, fetch = FetchType.EAGER)
    @JoinTable(joinColumns = {
            @JoinColumn(name = "domain_id")
    }, inverseJoinColumns = {
            @JoinColumn(name = "code")
    })
    @NotEmpty
    @Valid // needed to recur because we specify network codes when creating the domain
    private Set<NetworkCode> networkCodes = new HashSet<>();

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(joinColumns = {
            @JoinColumn(name = "parent", referencedColumnName = "domain_id")
    }, inverseJoinColumns = {
            @JoinColumn(name = "child", referencedColumnName = "domain_id")
    })
    private Set<Domain> operators = new HashSet<>();
    // more
}

I would expect this single query to fetch the Set<NetworkCode> and Set<Domain> relations, but it doesn't. Say that the Domain I query has two operators, Hibernate would perform 1 + 2 * 2 = 5 queries

Hibernate: select distinct domain0_.domain_id as domain1_1_0_, domain2_.domain_id as domain1_1_1_, networkcod4_.code as code2_2_, domain0_.name as name1_0_, domain0_.type as type1_0_, domain2_.name as name1_1_, domain2_.type as type1_1_, operators1_.parent as parent1_0__, operators1_.child as child4_0__, networkcod3_.domain_id as domain1_1_1__, networkcod3_.code as code5_1__ from domain domain0_ left outer join domain_operators operators1_ on domain0_.domain_id=operators1_.parent left outer join domain domain2_ on operators1_.child=domain2_.domain_id inner join domain_network_codes networkcod3_ on domain0_.domain_id=networkcod3_.domain_id inner join network_code networkcod4_ on networkcod3_.code=networkcod4_.code where domain0_.domain_id=?
Hibernate: select operators0_.parent as parent1_1_, operators0_.child as child4_1_, domain1_.domain_id as domain1_1_0_, domain1_.name as name1_0_, domain1_.type as type1_0_ from domain_operators operators0_ inner join domain domain1_ on operators0_.child=domain1_.domain_id where operators0_.parent=?
Hibernate: select networkcod0_.domain_id as domain1_1_1_, networkcod0_.code as code5_1_, networkcod1_.code as code2_0_ from domain_network_codes networkcod0_ inner join network_code networkcod1_ on networkcod0_.code=networkcod1_.code where networkcod0_.domain_id=?
Hibernate: select operators0_.parent as parent1_1_, operators0_.child as child4_1_, domain1_.domain_id as domain1_1_0_, domain1_.name as name1_0_, domain1_.type as type1_0_ from domain_operators operators0_ inner join domain domain1_ on operators0_.child=domain1_.domain_id where operators0_.parent=?
Hibernate: select networkcod0_.domain_id as domain1_1_1_, networkcod0_.code as code5_1_, networkcod1_.code as code2_0_ from domain_network_codes networkcod0_ inner join network_code networkcod1_ on networkcod0_.code=networkcod1_.code where networkcod0_.domain_id=?

I'm guessing this is because I'm joining the operators Domain elements but they have to join themselves. Is there an HQL query I can execute that would do both?

解决方案

If you know that you have only two levels in your tree, have you thought of joining deeper one level. Something like below?

SELECT DISTINCT domain FROM Domain domain 
  LEFT OUTER JOIN FETCH domain.operators operators1 
  LEFT OUTER JOIN FETCH domain.networkCodes 
  LEFT OUTER JOIN FETCH operators1.operators operators2 
  LEFT OUTER JOIN FETCH operators1.networkCodes
WHERE domain.domainId = :domainId

这篇关于Hibernate HQL连接获取不是递归获取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆