Spring Data 3 FETCH JOIN с подкачкой и спецификациями не работает должным образом, это подкачка в памятиJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Spring Data 3 FETCH JOIN с подкачкой и спецификациями не работает должным образом, это подкачка в памяти

Сообщение Anonymous »

Я использую Spring Boot 3 со спецификациями Jpa для создания динамического запроса, объединения страниц и выборки, чтобы избежать проблемы с запросом N+1. Но нумерация страниц применяется на уровне приложения в памяти, а не на уровне базы данных с запросом, как должно быть.
Моя сущность пользователя

Код: Выделить всё

@Entity
@Table(name = "users")
public class User implements UserDetails, Serializable {

@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;

@Column(name = "names")
private String names;

@ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
@JoinTable(name = "users_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set roles = new HashSet();

...
}
Мой репозиторий пользователей

Код: Выделить всё

@Repository
public interface UserRepository extends
JpaRepository, JpaSpecificationExecutor { ... }
Мой UserGateway использует UserRepository.findAll (спецификация, постраничная страница)

Код: Выделить всё

@Repository
@RequiredArgsConstructor
public class UserGatewayImpl implements UserGateway {

private final UserRepository userRepository;

@Override
public Page findByParams(UserSearchCommand searchCriteria, Pageable pageable) {

var userSpecification = buildCriteria(searchCriteria);

return userRepository.findAll(userSpecification, pageable);
}
}
Мои критерии сборки. Чтобы избежать исключения «org.hibernate.query.SemanticException: запрос указанного соединения, но владелец выбранной ассоциации не присутствовал в списке выбора», поскольку JPA выполняет 2 запроса, я проверяю resultType, чтобы узнать, является ли это запросом подсчета. Как в этом ответе. Получить соединение с помощью пейджингового решения

Код: Выделить всё

    private Specification buildCriteria(UserSearchCommand queryCriteria) {

return (root, criteriaQuery, criteriaBuilder) -> {
List
 predicates = new ArrayList();

if (Long.class != criteriaQuery.getResultType() &&
long.class != criteriaQuery.getResultType()) {
root.fetch("roles", JoinType.LEFT);
} else {
root.join("roles", JoinType.LEFT);
}

if (nonNull(queryCriteria.getNames())) {
predicates
.add(criteriaBuilder.and(
criteriaBuilder.equal(root.get("names"), queryCriteria.getNames())));
}

return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
};
}
Кажется, это работает. Пагинация «работает». Но когда мы смотрим на консоль и проверяем запрос, сгенерированный спящим режимом, я вижу, что нумерация страниц не применяется в запросе на уровне базы данных. Пагинация применяется на уровне приложения в памяти.
Сгенерированный запрос

Код: Выделить всё

...
from
users u1_0
left join
(users_roles r1_0
join
roles r1_1
on r1_1.id=r1_0.role_id)
on u1_0.id=r1_0.user_id
where
1=1
order by
u1_0.id desc
Я хочу использовать спецификации JPA, разбиение на страницы и FETCH JOIN вместе, но разбиение на страницы применяется на уровне приложения в памяти. Разбиение на страницы должно применяться на уровне базы данных в запросе.

Подробнее здесь: https://stackoverflow.com/questions/756 ... g-properly
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»