我的项目中的三个模型对象(本文末尾的模型和存储库片段)之间确实存在关系。
当我调用PlaceRepository.findById
时,它会触发三个select查询:
(“sql”)
从id=arg的p处选择*
从用户u中选择*,其中u.id=place.user.id
在c.woj_id=s.id,其中c.id=place.city.id上从城市c左外部连接状态s中选择*
(对我来说)那是相当不寻常的行为。在阅读Hibernate文档后,我认为它应该始终使用连接查询。当Place
类中的FetchType.LAZY
更改为FetchType.EAGER
时,查询没有区别(使用附加选择进行查询),当FetchType.LAZY
更改为FetchType.EAGER
时,城市类的查询也一样(使用JOIN进行查询)。
当我使用CityRepository.findById
抑制火灾时,有两种选择:
从城市c中选择*,其中id=arg
从州s中选择*,其中id=city.state.id
我的目标是在所有情况下都有一个sam行为(总是JOIN或SELECT,但JOIN首选)。
模型定义:
地点:
@Entity
@Table(name = "place")
public class Place extends Identified {
@Fetch(FetchMode.JOIN)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id_user_author")
private User author;
@Fetch(FetchMode.JOIN)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "area_city_id")
private City city;
//getters and setters
}
城市:
@Entity
@Table(name = "area_city")
public class City extends Identified {
@Fetch(FetchMode.JOIN)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "area_woj_id")
private State state;
//getters and setters
}
存储库:
存储库
public interface PlaceRepository extends JpaRepository<Place, Long>, PlaceRepositoryCustom {
Place findById(int id);
}
用户仓库:
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findAll();
User findById(int id);
}
城市报告:
public interface CityRepository extends JpaRepository<City, Long>, CityRepositoryCustom {
City findById(int id);
}
Spring-jpa使用实体管理器创建查询,如果查询是由实体管理器构建的,Hibernate将忽略读取模式。
以下是我使用的解决方法:
>
重写方法getQuery(规范
@Override
protected TypedQuery<T> getQuery(Specification<T> spec, Sort sort) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<T> query = builder.createQuery(getDomainClass());
Root<T> root = applySpecificationToCriteria(spec, query);
query.select(root);
applyFetchMode(root);
if (sort != null) {
query.orderBy(toOrders(sort, root, builder));
}
return applyRepositoryMethodMetadata(entityManager.createQuery(query));
}
在方法的中间,添加<代码> Apple YoFixMoad(root);
应用获取模式,使Hibernate使用正确的联接创建查询。
(不幸的是,我们需要从基类复制整个方法和相关的私有方法,因为没有其他扩展点。)
实施
applyFetchMode
:
private void applyFetchMode(Root<T> root) {
for (Field field : getDomainClass().getDeclaredFields()) {
Fetch fetch = field.getAnnotation(Fetch.class);
if (fetch != null && fetch.value() == FetchMode.JOIN) {
root.fetch(field.getName(), JoinType.LEFT);
}
}
}
首先,@Fetch(FetchMode.JOIN)
和@manytone(Fetch=FetchType.LAZY)
是对立的,因为@Fetch(FetchMode.JOIN)
相当于JPAFetchType.EAGER
。
急切抓取很少是一个好的选择,对于可预测的行为,最好使用查询时间JOIN FETCH
指令:
public interface PlaceRepository extends JpaRepository<Place, Long>, PlaceRepositoryCustom {
@Query(value = "SELECT p FROM Place p LEFT JOIN FETCH p.author LEFT JOIN FETCH p.city c LEFT JOIN FETCH c.state where p.id = :id")
Place findById(@Param("id") int id);
}
public interface CityRepository extends JpaRepository<City, Long>, CityRepositoryCustom {
@Query(value = "SELECT c FROM City c LEFT JOIN FETCH c.state where c.id = :id")
City findById(@Param("id") int id);
}
我认为Spring数据忽略了FetchMode。在处理Spring数据时,我总是使用@NamedEntityGraph
和@EntityGraph
注释
@Entity
@NamedEntityGraph(name = "GroupInfo.detail",
attributeNodes = @NamedAttributeNode("members"))
public class GroupInfo {
// default fetch mode is lazy.
@ManyToMany
List<GroupMember> members = new ArrayList<GroupMember>();
…
}
@Repository
public interface GroupRepository extends CrudRepository<GroupInfo, String> {
@EntityGraph(value = "GroupInfo.detail", type = EntityGraphType.LOAD)
GroupInfo getByGroupName(String name);
}
请检查此处的文档
问题内容: 我确实在项目中的三个模型对象之间有关系(文章末尾的模型和存储库片段)。 当我调用它时,会触发三个选择查询: (“ sql”) (对我而言)这是非常不正常的行为。据阅读Hibernate文档后所知,它应该始终使用JOIN查询。在类中更改为 查询时(带有附加SELECT 的查询)没有任何区别,而在类更改为 (使用JOIN查询时)则没有变化。 当我使用抑制射击时,有两个选择: 我的目标是在所
在Spark中是如何工作的? 如果我们注册一个对象作为一个表,会将所有数据保存在内存中吗?
我从网上和论坛上看到了关于BatchSize的相关主题,但我仍然不明白一些部分。所以让我们描述一下我理解的和不理解的。 批量取数:选择取数的优化策略。Hibernate通过指定主键或外键列表,在一次选择中检索一批实体实例或集合。 让我们有JPA 2.0,带有Hibernate实现。这些实体: } 因此,我懒得去了解产品中的制造商。因此,当我执行select fetching时,就完成了。所以我有很
我经常把文本输出到文件中。我想知道:是如何工作的? 当我调用时,它是否在文件上写入文本?如果它不写文本,我需要使用flush函数来写数据吗? 例如: 如果while循环中发生错误,文件将在不写入数据的情况下关闭。如果我在while循环中使用函数,那么为什么要使用?如果我错了,请纠正我。
我正从最基本的方面着手研究递归,因为我在过去很挣扎。我在看这个阶乘解: 因此函数会一直调用自己,直到<code>n==0</code>为止。然后在每次调用时返回值。这就是我不明白的:当它从基本条件返回时,它返回一个值,并不断添加每个调用的值。 这些值存储在哪里,以便最终能够返回总和?