当前位置: 首页 > 知识库问答 >
问题:

HibernateHQL连接提取不递归提取

孙承
2023-03-14

我有以下查询和方法

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();
}

使用< code >域作为

@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
}

我希望这个查询能够获取Set

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=?

我猜这是因为我加入了operators Domain元素,但是它们必须加入自己。

有没有我可以执行的HQL查询可以两者兼得?


共有3个答案

尉迟正平
2023-03-14

您标记了您的协会渴望。因此,无论您在查询中执行什么操作,Hibernate 都将加载所有关联的域和已加载域的网络代码。它将加载其他域的域和网络代码等,直到所有集合加载返回已加载的空集合或实体。

为避免这种情况,请使您的集合变懒(默认情况下是这样)。然后加载一个包含其运算符和网络代码的域将加载它。

郭麒
2023-03-14

Hibernate关系适用于不同的获取策略..!!

Hibernate提供了4种检索数据的策略:

选择

@OneToMany(mappedBy="tableName", cascade=CascadeType.ALL)
@Column(name="id") 
@Fetch(FetchMode.SELECT)

在这个方法中,有多个SQL被触发。第一个被触发是为了检索父表中的所有记录。其余的被触发是为了检索每个父记录的记录。这基本上是N 1问题。第一个查询从数据库中检索N条记录,在这种情况下是N条父记录。对于每个父级,一个新的查询检索子级。因此对于N个父级,N个查询从子级表中检索信息。

加入

@OneToMany(mappedBy="tableName", cascade=CascadeType.ALL)
@Column(name="id")
@Fetch(FetchMode.JOIN) 

这与SELECT读取策略类似,只是所有数据库检索都在JOIN读取中预先进行,这与SELECT中根据需要进行的检索不同。这可能成为一个重要的性能考虑因素。

订阅

 @OneToMany(mappedBy="tableName", cascade=CascadeType.ALL)
 @Column(name="id")
 @Fetch(FetchMode.SUBSELECT)

两个SQL被触发。一个用于检索所有父级,第二个使用WHERE子句中的SUBSELECT查询来检索具有匹配父级ID的所有子级。

批次

@OneToMany(mappedBy="tableName", cascade=CascadeType.ALL)
@Column(name="id")
@@BatchSize(size=2)

批次大小映射到检索其子级的父级的数量。因此,我们可以指定一次要提取的记录数。但将执行多个查询。!!

一对多

多对一

Hibernate还区分(何时获取关联)

1.Immediate迷人-

加载Parent时,会立即获取关联、集合或属性。(惰性=“false”)

2.Lazy收集-

当应用程序调用集合上的操作时,会获取该集合。(这是集合的默认值。(lazy="true ")

3.“超懒惰”集合取数-

根据需要从数据库中访问集合的各个元素。Hibernate 尝试不将整个集合提取到内存中,除非绝对需要(适用于非常大的集合)(懒惰=“额外”)

4.代理提取-

当在关联对象上调用标识符getter以外的方法时,将获取单值关联。(惰性="代理")

5.“无代理”获取-

访问实例变量时会获取单值关联。与代理获取相比,这种方法不那么懒惰。(懒="no-agent")

6.Lazy属性获取-

访问实例变量时,将提取属性或单值关联。(懒惰=“真”)

一对多

多对一

沈曜灿
2023-03-14

如果你知道你的树只有两层,你是否想过加入更深的一层。像下面这样的?

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
 类似资料:
  • 问题内容: 我有以下查询和方法 与作为 我希望这个查询可以获取and >关系,但事实并非如此。假设I查询有两个运算符,Hibernate将执行1 + 2 * 2 = 5个查询 我猜这是因为我加入了operator 元素,但他们必须加入自己的行列。 我可以执行同时执行的HQL查询吗? 问题答案: 如果您知道树中只有两个级别,那么您是否考虑过加入更深的一个级别。像下面的东西?

  • 我在使用LEFT JOIN FETCH时遇到了一个问题。请参考我下面的实体和存储库。 考虑一个场景,可选的课程不会在任何时间点从表中删除。但是学生信息可以被删除。数据库中的两个表之间没有主键和外键关系。只是我们有一个共同的栏目“学生ID”。 不带事务的服务方法: 具有事务性的服务方法: 尽管我使用了LEFT JOIN FETCH,但当我调用依赖实体(即oc)时,为什么在学生记录不存在的情况下(即学

  • 我有一个结构如下的表格,其中包含有关俱乐部会员的信息 我对后来重新加入的成员感兴趣。对于上述数据,在整个期间,这样做了一次,没有,而这样做了两次。 每次发生这种情况,从他们的会员资格结束到他们重新加入的时间是多少?对于上述数据,这将是: 我很乐意得到使用R(理想情况下使用dplyr)或SQL(MySQL)的答案

  • 这是我的命名查询: @NamedQuery(name=“User.findOneWithLists”,query=“从用户u中选择u”“左连接获取u.aTemplates”“左连接获取u.bTemplates”“左连接获取u.bp”“左连接获取u.aCredentials”“左连接获取u.st WHERE(st.deleted=false)”“左连接获取u.bCredentials”“左连接获取u

  • null 如何在employee实体中只取Dept.name列而不是整个Department行(需要避免对Department进行的大量集合进行急切的取数)?如果是,我应该使用什么注释? 如何在此方案中处理级联?

  • 在cherry-pick,您可以从其他分支复制指定的提交,然后导入到现在的分支。 主要使用的场合: 把弄错分支的提交移动到正确的地方 把其他分支的提交添加到现在的分支