На основании ваших комментариев, учитывая, что Project
не может быть неназначенным из Contractor
после того, как эта ссылка сделана, и что вы заинтересованы только в изменениях, внесенных в упомянутые проекты, связанные сДля данного экземпляра Contractor
наилучшим способом получения рассматриваемой информации, вероятно, будет выполнение нескольких запросов аудита для построения этого представления.
Первое, что вам нужно, это список Project
идентификаторов, которыесвязаны с этим Contractor
.Вы можете получить эту информацию из таблиц аудита, но я полагаю, что было бы лучше просто получить ее непосредственно из данных обычных сущностей.
SELECT p.id FROM Contractor c JOIN c.projects p WHERE c.id = :contractorId
Вышеупомянутый запрос в основном является проекционным запросом, который даетидентификатор подрядчика, вы получаете все идентификаторы проекта, которые связаны с подрядчиком через ассоциацию проектов.
Если вы хотите получить это через таблицы аудита, первое, что нам нужно определить, этомаксимальный номер редакции для подрядчика, поэтому мы выбираем правильный снимок данных.
// you might want to check if this collection is empty
// it should not be assuming you aren't removing data from the audit tables
// but sometimes people archive data, so its best to be thorough
List<Number> revs = reader.getRevisions( Contractor.class, contractorId );
// The list of revisions are always in ascending order, so grab the last entry.
Number maxRevision = revs.get( revs.size() - 1 );
// Build the projection query
// This returns us the list of project ids, just like the HQL above
List projectIds = reader.createQuery()
.forEntitiesAtRevision( Contractor.class, maxRevision )
.traverseRelation( "projects", JoinType.INNER )
.addProjection( AuditEntity.property( "id" ).distinct() )
.up()
.add( AuditEntity.id().eq( contractorId ) )
.getResultList();
Получив эту информацию, все сводится к выполнению запроса аудита в цикле для каждого Project
, чтобы определить информациювам нужно.
for ( Object projectId : projectIds ) {
List results = reader.createQuery()
.forRevisionsOfEntity( Project.class, false, false )
.add( AuditEntity.id().eq( projectId ) )
.addOrder( AuditEntity.revisionNumber().asc() );
// At this point you have an list of object array values
// Index 0 - This is the instance of Project
// Index 1 - This is the revision entity, you can get the rev # and timestamp
// Index 2 - Type of revision, see RevisionType
//
// So you can basically iterate the list in ascending order keeping track of
// the prior Project and build a changeset for each project.
//
// This approach is often more efficient if you're needing to compare multiple
// attributes on an entity rather than issuing a query to the database for
// each change made to a single property.
}
В следующем основном выпуске Envers будут некоторые дополнительные методы запросов, которые позволят вам получить массив объектов, состоящий из следующих
// Index 0 - This is the instance of Project
// Index 1 - This is the revision entity, you can get the rev # and timestamp
// Index 2 - Type of revision, see RevisionType
// Index 3 - Array of properties changed at this revision
Ключевым моментом здесь является индекс 3 , где мы предоставимУ вас есть свойства, которые были изменены, поэтому вам не нужно рассчитывать их самостоятельно.