Критерии устойчивости. Выборка с угощением для конкретного типа.JAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Критерии устойчивости. Выборка с угощением для конкретного типа.

Сообщение Anonymous »

orderItems могут быть двух типов: StandardOrderItem иSpecificOrderItem
Я не хочу, чтобы они загружались, чтобы избежать исключения LazyInitialization.
Так и должно быть вот так

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

orderService.findOrderByIdAndEntityGraph(productionOrderId,
Map.of("orderItems",
new JPAUtils.JoinNode(
StandardOrderItem.class,
Map.of("components", new JPAUtils.JoinNode(EMPTY_MAP))
)));
ПосколькуSpecificOrderItem do ton содержит «компоненты»,
которые я хочу получить.
Так что, к сожалению, метод Join ленив, выборка нетерпится, но критерийBuilder.treat() работает только с объединениями, что приводит к ошибкам при объединении "компонентов"

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

public static  T getBySpecificationWithGraph(
EntityManager entityManager,
Specification specification,
Map joins,
Class clazz
) {
CriteriaQuery criteriaQuery = prepareCriteriaQuery(entityManager, specification, joins, clazz);
return entityManager.createQuery(criteriaQuery).getSingleResult();
}

public static  Specification fieldEquals(String fieldName, V value) {
return (root, criteriaQuery, criteriaBuilder) ->
criteriaBuilder.equal(root.get(fieldName), value);
}

private static  CriteriaQuery prepareCriteriaQuery(
EntityManager entityManager,
Specification specification,
Map joins,
Class clazz
) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(clazz);
Root ownerRoot = criteriaQuery.from(clazz);

// Apply fetch logic with TREAT
prepareFetch(joins, ownerRoot, null, criteriaBuilder);

criteriaQuery.select(ownerRoot)
.where(specification.toPredicate(ownerRoot, criteriaQuery, criteriaBuilder));
return criteriaQuery;
}

private static  void prepareFetch(
Map joins,
From fetch,
CriteriaBuilder criteriaBuilder
) {
joins.forEach((key, value) -> {
Fetch childFetch = null;
Join childJoin = null;  // Declare childJoin for TREAT usage

// Apply TREAT logic only on Fetches or Joins
if (fetch == null) {
if (value.getType() != null) {
// First, attempt to treat it as a collection join
try {
// If the relationship is a collection (e.g., @OneToMany)
SetJoin setJoin = root.joinSet(key, JoinType.LEFT);
childJoin = criteriaBuilder.treat(setJoin, value.getType());

root.fetch(key, JoinType.LEFT);  // Ensure the association is fetched eagerly
} catch (IllegalArgumentException | ClassCastException e) {
// If it's not a collection, treat it as a singular join (e.g., @ManyToOne, @OneToOne)
try {
Join join = root.join(key, JoinType.LEFT);
childJoin = criteriaBuilder.treat(join, value.getType());

root.fetch(key, JoinType.LEFT);  // Ensure the association is fetched eagerly
} catch (IllegalArgumentException | ClassCastException ex) {
throw new RuntimeException("Unable to apply TREAT to the join: " + key, ex);
}
}
} else {
// If no type is provided, just fetch the relationship
childFetch = root.fetch(key, JoinType.LEFT);
}
} else {
childFetch = fetch.fetch(key, JoinType.LEFT);
}

// Handle recursive joins and fetches for deeper relationships
Objects.requireNonNull(value);
Map next = value.getJoins();

if (!next.isEmpty()) {
// Use childJoin for TREAT case or childFetch for normal cases
if (childJoin != null) {
prepareFetch(next, childJoin, null, criteriaBuilder);  // Continue joining with TREAT
} else {
prepareFetch(next, root, childFetch, criteriaBuilder);  // Continue fetching
}
}
});
}

@Getter
public static class JoinNode {
private final Class type;
private final Map joins;

public JoinNode(Class type, Map  joins) {
this.type = type;
this.joins = joins;
}

public JoinNode(Map joins) {
this.joins = joins;
this.type = null;
}
}
Использование:

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

orderService.findOrderByIdAndEntityGraph(productionOrderId,
Map.of("orderItems",
new JPAUtils.JoinNode(
StandardOrderItem.class,
Map.of("components", new JPAUtils.JoinNode(EMPTY_MAP))
)));
Объяснение:
orderItems могут быть двух типов: StandardOrderItem иSpecificOrderItem
Я не хочу, чтобы они загружались, чтобы избежать исключения LazyInitialization.
Так должно быть

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

orderService.findOrderByIdAndEntityGraph(productionOrderId,
Map.of("orderItems",
new JPAUtils.JoinNode(
StandardOrderItem.class,
Map.of("components", new JPAUtils.JoinNode(EMPTY_MAP))
)));
ПосколькуSpecificOrderItem do ton содержит «компоненты»,
которые я хочу получить.
Так что, к сожалению, метод Join ленив, выборка нетерпится, но критерийBuilder.treat() работает только с соединениями, что приводит к ошибкам при объединении «компонентов»

Подробнее здесь: https://stackoverflow.com/questions/790 ... cific-type
Реклама
Ответить Пред. темаСлед. тема

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

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

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

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

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

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