我使用hibernate spring-data-jpa和querydsl进行分页,并且我只使用@BatchSize(size=10)
一次数据库往返.
@Entity
@Table(name = "appel_offre", catalog = "ao")
public class AppelOffre implements java.io.Serializable {
....
@OneToMany(fetch = FetchType.LAZY, mappedBy = "appelOffre")
@BatchSize(size=10)
public Set<AoActivite> getAoActivites() {
return this.aoActivites;
}
Run Code Online (Sandbox Code Playgroud)
并且:
@Entity
@Table(name = "ao_activite", catalog = "ao")
public class AoActivite implements java.io.Serializable {
.....
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ID_ACTIVITE", nullable = false)
@BatchSize(size=10)
public Activite getActivite() {
return this.activite;
}
Run Code Online (Sandbox Code Playgroud)
我的查询
JPAQuery query = new JPAQuery(entityManager).from(ao)
.leftJoin( ao.acheteur, ach ).fetch()
.leftJoin( ao.aoActivites , ao_ac )
.leftJoin( …
Run Code Online (Sandbox Code Playgroud) 我有一个@ManyToOne
关系的实体,我想用一个查询检索,因此使用@Fetch(FetchMode.JOIN)
.有时Hibernate不尊重并发布N + 1 SELECT
.随着有时我的意思是,因为我不知道是什么触发它,我有案件对不同的查询,这可能发生,或者不一样的类.
这是一个带有我使用的注释的简化实体:
@Entity
public class Employee {
@ManyToOne
@Fetch(FetchMode.JOIN)
private Department department;
}
Run Code Online (Sandbox Code Playgroud)
同
CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class);
Root<Employee> root = criteriqQuery.from(Employee.class);
TypedQuery<Employee> typedQuery = entityManager.createQuery(criteriaQuery);
List<Employee> employees = typedQuery.getResultList();
Run Code Online (Sandbox Code Playgroud)
我希望一个查询来获取两个Employee
及Department
,像
select ... from Employee join Department on ...
Run Code Online (Sandbox Code Playgroud)
相反,我得到所有N的Employee
第一个选择,然后SELECT
是所有Department
s的N s(考虑没有缓存).
我发现了许多类似的问题,但他们的答案提出了解决方法,并没有解释为什么会发生这种情况.请避免建议使用延迟加载的答案:这不是我问的问题.
我正在使用 spring boot、spring data 和 Hibernate 开发一个应用程序。我有一个实体“Client”,它与另一个实体“Reservation”具有“onetomany”关系,如下所示:
@Entity
public class Client implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany( mappedBy = "client", fetch=FetchType.EAGER)
@Fetch(value = FetchMode.JOIN)
private Set<Reservation> reservations = new HashSet<>();
}
Run Code Online (Sandbox Code Playgroud)
我已经实现了 JpaRepository 接口,所以我可以操作客户端数据:
public interface ClientRepository extends JpaRepository<Client, Long> {}
Run Code Online (Sandbox Code Playgroud)
在服务类中,我实现了一种方法来查找数据库中的所有客户端:
@Service
public class ClientService {
@Autowired
private ClientRepository clientRepository;
@Transactional(readOnly = true)
public List<Client> findAll() {
return clientRepository.findAll();
}}
Run Code Online (Sandbox Code Playgroud)
findAll() 的执行运行良好并返回所有客户端及其保留。但是,在我的 sql 日志中,我已经执行了 N+1 个查询(N 是客户端的计数),尽管我已经fetch=FetchType.EAGER
在我的客户端实体中设置了这些查询。我认为 hibernate 将创建一个单一的查询,在其中加入所有必要的数据以检索客户及其预订。
因此,我被迫通过查询明确加入客户和预订:
@Query("select client …
Run Code Online (Sandbox Code Playgroud)