假设我有3个模型,如下所示:
@Entity
@Data
class Continent {
@Id
private Long id;
private String name;
...
}
@Entity
@Data
class Country {
@Id
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
private Continent continent;
private String name;
...
}
@Entity
@Data
class City {
@Id
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
private Country country;
private String name;
...
}
我想用它的主键来取大陆 id
. 但我也希望所有属于一个大陆的国家和所有属于一个国家的城市。
目前我正在进行3个单独的调用,首先查询大陆表,然后按fk大陆id查询国家表,最后按fk国家id查询城市表。
我想在一次通话中查询所有内容。因此,我添加了双向onetomany关系和急切抓取,如下所示:
@Entity
@Data
class Continent {
@Id
private Long id;
private String name;
...
@OneToMany(mappedBy = "continent", fetch = FetchType.EAGER)
private List<Country> countries;
}
@Entity
@Data
class Country {
@Id
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
private Continent continent;
private String name;
...
@OneToMany(mappedBy = "country", fetch = FetchType.EAGER)
private List<City> cities;
}
@Entity
@Data
class City {
@Id
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
private Country country;
private String name;
...
}
一切正常。我在hibernate生成的查询中看到两个左外连接。
现在的问题是,我不想每次都急切地获取所有相关的关联。一种选择是将所有onetomany关联都更改为lazy和have join fetch
在jpql查询中。
因此,为了获取一个大陆的所有国家,我可以使用如下jpql查询
SELECT u FROM Continent u JOIN FETCH u.countries WHERE u.id=?1
但是对于像continent->country->city这样的层次结构,我也希望填充city字段,我无法设计jpql查询。你知道我该怎么做吗?
编辑:未来的读者可能对阅读jpa感兴趣:如何为3个级别定义@namedentitygraph?
2条答案
按热度按时间brgchamk1#
你可以用例如。
@EntityGraph
,但我认为这是blaze持久性实体视图的完美用例。我创建了这个库,以便在jpa模型和自定义接口或抽象类定义的模型之间进行简单的Map,比如spring数据在steroids上的投影。其思想是以您喜欢的方式定义目标结构(域模型),并通过jpql表达式将属性(getter)Map到实体模型。
对于blaze持久性实体视图,用例的dto模型可以如下所示:
查询是将实体视图应用于查询的问题,最简单的就是按id进行查询。
ContinentDto a = entityViewManager.find(entityManager, ContinentDto.class, id);
spring数据集成允许您像spring数据投影一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_us/index.html#spring-数据特征vshtjzan2#
我想出了以下方法。
首先,我将所有关联标记为懒惰:
大陆模式
国家模式
接下来,我创建了存储库并添加了jpql查询,以连接和获取所需的关联
接下来,在我的服务类中,当我想在大陆上加载初始化的所有国家和城市字段时,我执行如下调用:
基本上,这首先会加载所有经过筛选的国家
continentId
在第一次调用中初始化城市,然后在第二次调用中加载整个大陆的所有国家。因此,所有关联都加载到当前持久性上下文中。