Подменю Envers @ManyToMany

У меня есть проверенный объект A. Entity A содержит поле «имя» и набор объектов B (аннотируется как отношение «многие ко многим»). Я создал экземпляр A, определенное имя, коллекцию объектов B и сохранил все это в БД. Это ревизия №1. Затем я изменил имя A и обновил его в БД. Это ревизия №2. Я использую следующий метод, чтобы получить все сущности класса A в редакции # 2

List list = getAuditReader().createQuery().forEntitiesAtRevision(A.class, 2)
    .add(AuditEntity.revisionNumber().eq((int) revisionId)).getResultList();

Я получаю объект A в редакции # 2, но Envers также выбирает набор объектов B, связанных с этим A, из ревизии # 1. Здесь пример запроса, используемого Envers:

SELECT a_b_aud.a_id, a_b_aud.b_id
FROM   a_b_aud CROSS JOIN b_aud
WHERE  a_b_aud.b_id=b_aud.id 
       AND b_aud.rev=(SELECT max(b_aud2.rev)) FROM b_aud AS b_aud2 WHERE b_aud2.rev<=2 AND b_aud.id=b_aud2.id)
       AND a_b_aud.rev=(SELECT max(a_b_aud2.rev)) FROM a_b_aud AS a_b_aud2 WHERE a_b_aud2.rev<=2 AND a_b_aud.a_id=a_b_aud2.a_id AND a_b_aud.b_id=a_b_aud2.b_id)

Но на самом деле мне нужен NULL как совокупность объектов B в случае отсутствия изменений для него в редакции № 2 (из-за проблемы с производительностью).

В этом запросе есть два подзапроса. И если у нас есть более одного набора объектов, связанных с A (C, D, E, F) и для примерно 100 тысяч строк для каждого b_aud и a_b_aud, указанный выше запрос занимает много времени. Я определил объект B как не проверенный (т. Е. Не добавил @Audited аннотацию в B) и определил отношение A B следующим образом:

@ManyToMany
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
@JoinTable(name = "a_b", joinColumns = @JoinColumn(name = a_id))
@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
public Set getBs();

Он фиксирует первый SUBSELECT. Но я не могу найти стандартное решение, чтобы не запрашивать B, если он не существует для запрошенной ревизии (в моем случае № 2). Таким образом, запрос должен выглядеть так:

SELECT a_b_aud.a_id, a_b_aud.b_id
FROM   a_b_aud CROSS JOIN b_aud
WHERE  a_b_aud.b_id=b_aud.id b_aud.rev=2 AND a_b_aud.rev=2

Единственное решение, которое я нашел, это использование собственного SQL-запроса и его выполнение с использованием шаблона спящего режима. Затем преобразуйте значения результата в объект A, используя ResultTransformer.

Может ли кто-нибудь помочь в этом вопросе? Есть ли стандартная конфигурация/аннотация, которую мне нужно добавить, чтобы избежать второго SUBSELECT?

0
nl ja de

1 ответы

В Envers нет возможности не загружать связанные объекты по запросу. Однако не следует, что объекты B always загружаются лениво (независимо от аннотаций относительно отношения), поэтому, если вы не хотите выполнять запрос, который их загружает, просто не обращайтесь к этому полю.

Если вы хотите повысить производительность чтения, вы также можете посмотреть стратегию проверки достоверности, см. http://docs.jboss.org/hibernate/core/4.1/devguide/en-US/html/ch15.html#d5e4085 . Он быстрее читает, но медленнее пишет.

0
добавлено