HHH-11595 Introduce `CollectionAuditTable` support
This commit is contained in:
parent
d9fa35c6f1
commit
99c13e5965
|
@ -350,6 +350,9 @@ It may be tedious to add this annotation to every audited entity, so if possible
|
||||||
If you have a mapping with secondary tables, audit tables for them will be generated in the same way (by adding the prefix and suffix).
|
If you have a mapping with secondary tables, audit tables for them will be generated in the same way (by adding the prefix and suffix).
|
||||||
If you wish to overwrite this behavior, you can use the `@SecondaryAuditTable` and `@SecondaryAuditTables` annotations.
|
If you wish to overwrite this behavior, you can use the `@SecondaryAuditTable` and `@SecondaryAuditTables` annotations.
|
||||||
|
|
||||||
|
If you have a mapping with collection tables, the audit table for them will be generated in the same way (by using the prefix and suffix).
|
||||||
|
If you wish to overwrite this behavior, you can use the `@CollectionAuditTable` annotations.
|
||||||
|
|
||||||
If you'd like to override auditing behavior of some fields/properties inherited from `@MappedSuperclass` or in an embedded component,
|
If you'd like to override auditing behavior of some fields/properties inherited from `@MappedSuperclass` or in an embedded component,
|
||||||
you can apply the `@AuditOverride` annotation on the subtype or usage site of the component.
|
you can apply the `@AuditOverride` annotation on the subtype or usage site of the component.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import org.hibernate.Incubating;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows for the customization of an Envers audit collection table.
|
||||||
|
*
|
||||||
|
* @author Chris Cranford
|
||||||
|
*/
|
||||||
|
@Incubating
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||||
|
public @interface CollectionAuditTable {
|
||||||
|
/**
|
||||||
|
* The name of the table
|
||||||
|
*/
|
||||||
|
String name();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The schema of the table. Defaults to the schema of the mapping.
|
||||||
|
*/
|
||||||
|
String schema() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The catalog of the table. Defaults to the catalog of the mapping.
|
||||||
|
*/
|
||||||
|
String catalog() default "";
|
||||||
|
}
|
|
@ -80,7 +80,7 @@ public abstract class AbstractMetadataGenerator {
|
||||||
|
|
||||||
protected String getSchemaName(String schemaFromAnnotation, Table table) {
|
protected String getSchemaName(String schemaFromAnnotation, Table table) {
|
||||||
String schemaName = schemaFromAnnotation;
|
String schemaName = schemaFromAnnotation;
|
||||||
if ( StringTools.isEmpty(schemaName ) ) {
|
if ( StringTools.isEmpty( schemaName ) ) {
|
||||||
schemaName = metadataBuildingContext.getConfiguration().getDefaultSchemaName();
|
schemaName = metadataBuildingContext.getConfiguration().getDefaultSchemaName();
|
||||||
if ( StringTools.isEmpty( schemaName ) ) {
|
if ( StringTools.isEmpty( schemaName ) ) {
|
||||||
schemaName = table.getSchema();
|
schemaName = table.getSchema();
|
||||||
|
@ -91,7 +91,7 @@ public abstract class AbstractMetadataGenerator {
|
||||||
|
|
||||||
protected String getCatalogName(String catalogFromAnnotation, Table table) {
|
protected String getCatalogName(String catalogFromAnnotation, Table table) {
|
||||||
String catalogName = catalogFromAnnotation;
|
String catalogName = catalogFromAnnotation;
|
||||||
if ( StringTools.isEmpty(catalogName ) ) {
|
if ( StringTools.isEmpty( catalogName ) ) {
|
||||||
catalogName = metadataBuildingContext.getConfiguration().getDefaultCatalogName();
|
catalogName = metadataBuildingContext.getConfiguration().getDefaultCatalogName();
|
||||||
if ( StringTools.isEmpty( catalogName ) ) {
|
if ( StringTools.isEmpty( catalogName ) ) {
|
||||||
catalogName = table.getCatalog();
|
catalogName = table.getCatalog();
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.envers.configuration.internal.metadata;
|
package org.hibernate.envers.configuration.internal.metadata;
|
||||||
|
|
||||||
|
import org.hibernate.envers.CollectionAuditTable;
|
||||||
import org.hibernate.envers.boot.model.CompositeIdentifier;
|
import org.hibernate.envers.boot.model.CompositeIdentifier;
|
||||||
import org.hibernate.envers.boot.model.RootPersistentEntity;
|
import org.hibernate.envers.boot.model.RootPersistentEntity;
|
||||||
import org.hibernate.envers.boot.spi.EnversMetadataBuildingContext;
|
import org.hibernate.envers.boot.spi.EnversMetadataBuildingContext;
|
||||||
|
@ -23,7 +24,6 @@ import org.hibernate.envers.internal.tools.StringTools;
|
||||||
import org.hibernate.mapping.Collection;
|
import org.hibernate.mapping.Collection;
|
||||||
import org.hibernate.mapping.OneToMany;
|
import org.hibernate.mapping.OneToMany;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.Table;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
@ -194,17 +194,19 @@ public class MiddleTableCollectionMetadataGenerator extends AbstractCollectionMe
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Hibernate uses a middle table for mapping this relation, so we get its name directly.
|
// Hibernate uses a middle table for mapping this relation, so we get its name directly.
|
||||||
|
CollectionAuditTable collectionAuditTable = context.getPropertyAuditingData().getCollectionAuditTable();
|
||||||
|
if ( collectionAuditTable != null ) {
|
||||||
|
return collectionAuditTable.name();
|
||||||
|
}
|
||||||
return collection.getCollectionTable().getName();
|
return collection.getCollectionTable().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
private RootPersistentEntity createMiddleEntity(CollectionMetadataContext context, String tableName, String entityName) {
|
private RootPersistentEntity createMiddleEntity(CollectionMetadataContext context, String tableName, String entityName) {
|
||||||
final AuditJoinTableData joinTable = context.getPropertyAuditingData().getJoinTable();
|
|
||||||
final Table collectionTable = context.getCollection().getCollectionTable();
|
|
||||||
final AuditTableData auditTableData = new AuditTableData(
|
final AuditTableData auditTableData = new AuditTableData(
|
||||||
entityName,
|
entityName,
|
||||||
tableName,
|
tableName,
|
||||||
getSchemaName( joinTable.getSchema(), collectionTable ),
|
resolveSchema( context ),
|
||||||
getCatalogName( joinTable.getCatalog(), collectionTable )
|
resolveCatalog( context )
|
||||||
);
|
);
|
||||||
|
|
||||||
final RootPersistentEntity entity = new RootPersistentEntity( auditTableData, null );
|
final RootPersistentEntity entity = new RootPersistentEntity( auditTableData, null );
|
||||||
|
@ -229,6 +231,25 @@ public class MiddleTableCollectionMetadataGenerator extends AbstractCollectionMe
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String resolveSchema(CollectionMetadataContext context) {
|
||||||
|
final CollectionAuditTable collectionAuditTable = context.getPropertyAuditingData().getCollectionAuditTable();
|
||||||
|
if ( collectionAuditTable != null && !StringTools.isEmpty( collectionAuditTable.schema() ) ) {
|
||||||
|
return collectionAuditTable.schema();
|
||||||
|
}
|
||||||
|
|
||||||
|
final AuditJoinTableData joinTable = context.getPropertyAuditingData().getJoinTable();
|
||||||
|
return getSchemaName( joinTable.getSchema(), context.getCollection().getCollectionTable() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveCatalog(CollectionMetadataContext context) {
|
||||||
|
final CollectionAuditTable collectionAuditTable = context.getPropertyAuditingData().getCollectionAuditTable();
|
||||||
|
if ( collectionAuditTable != null && !StringTools.isEmpty( collectionAuditTable.catalog() ) ) {
|
||||||
|
return collectionAuditTable.catalog();
|
||||||
|
}
|
||||||
|
final AuditJoinTableData joinTable = context.getPropertyAuditingData().getJoinTable();
|
||||||
|
return getCatalogName( joinTable.getCatalog(), context.getCollection().getCollectionTable() );
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isRevisionTypeInId(CollectionMetadataContext context) {
|
private boolean isRevisionTypeInId(CollectionMetadataContext context) {
|
||||||
return isEmbeddableElementType( context ) || isLobMapElementType( context );
|
return isEmbeddableElementType( context ) || isLobMapElementType( context );
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.hibernate.envers.AuditMappedBy;
|
||||||
import org.hibernate.envers.AuditOverride;
|
import org.hibernate.envers.AuditOverride;
|
||||||
import org.hibernate.envers.AuditOverrides;
|
import org.hibernate.envers.AuditOverrides;
|
||||||
import org.hibernate.envers.Audited;
|
import org.hibernate.envers.Audited;
|
||||||
|
import org.hibernate.envers.CollectionAuditTable;
|
||||||
import org.hibernate.envers.NotAudited;
|
import org.hibernate.envers.NotAudited;
|
||||||
import org.hibernate.envers.RelationTargetAuditMode;
|
import org.hibernate.envers.RelationTargetAuditMode;
|
||||||
import org.hibernate.envers.RelationTargetNotFoundAction;
|
import org.hibernate.envers.RelationTargetNotFoundAction;
|
||||||
|
@ -540,6 +541,7 @@ public class AuditedPropertiesReader {
|
||||||
propertyData.setAccessType( accessType );
|
propertyData.setAccessType( accessType );
|
||||||
|
|
||||||
addPropertyJoinTables( property, propertyData );
|
addPropertyJoinTables( property, propertyData );
|
||||||
|
addPropertyCollectionAuditTable( property, propertyData );
|
||||||
addPropertyAuditingOverrides( property, propertyData );
|
addPropertyAuditingOverrides( property, propertyData );
|
||||||
if ( !processPropertyAuditingOverrides( property, propertyData ) ) {
|
if ( !processPropertyAuditingOverrides( property, propertyData ) ) {
|
||||||
// not audited due to AuditOverride annotation
|
// not audited due to AuditOverride annotation
|
||||||
|
@ -677,6 +679,13 @@ public class AuditedPropertiesReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addPropertyCollectionAuditTable(XProperty property, PropertyAuditingData propertyAuditingData) {
|
||||||
|
final CollectionAuditTable collectionAuditTableAnn = property.getAnnotation( CollectionAuditTable.class );
|
||||||
|
if ( collectionAuditTableAnn != null ) {
|
||||||
|
propertyAuditingData.setCollectionAuditTable( collectionAuditTableAnn );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the {@link AuditOverride} annotations.
|
* Add the {@link AuditOverride} annotations.
|
||||||
*
|
*
|
||||||
|
|
|
@ -14,6 +14,7 @@ import jakarta.persistence.EnumType;
|
||||||
|
|
||||||
import org.hibernate.envers.AuditOverride;
|
import org.hibernate.envers.AuditOverride;
|
||||||
import org.hibernate.envers.AuditOverrides;
|
import org.hibernate.envers.AuditOverrides;
|
||||||
|
import org.hibernate.envers.CollectionAuditTable;
|
||||||
import org.hibernate.envers.RelationTargetAuditMode;
|
import org.hibernate.envers.RelationTargetAuditMode;
|
||||||
import org.hibernate.envers.RelationTargetNotFoundAction;
|
import org.hibernate.envers.RelationTargetNotFoundAction;
|
||||||
import org.hibernate.envers.internal.entities.PropertyData;
|
import org.hibernate.envers.internal.entities.PropertyData;
|
||||||
|
@ -33,6 +34,7 @@ public class PropertyAuditingData {
|
||||||
private String beanName;
|
private String beanName;
|
||||||
private String mapKey;
|
private String mapKey;
|
||||||
private EnumType mapKeyEnumType;
|
private EnumType mapKeyEnumType;
|
||||||
|
private CollectionAuditTable collectionAuditTable;
|
||||||
private AuditJoinTableData joinTable;
|
private AuditJoinTableData joinTable;
|
||||||
private String accessType;
|
private String accessType;
|
||||||
private final List<AuditOverrideData> auditJoinTableOverrides = new ArrayList<>( 0 );
|
private final List<AuditOverrideData> auditJoinTableOverrides = new ArrayList<>( 0 );
|
||||||
|
@ -329,6 +331,14 @@ public class PropertyAuditingData {
|
||||||
this.virtualPropertyType = virtualPropertyType;
|
this.virtualPropertyType = virtualPropertyType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CollectionAuditTable getCollectionAuditTable() {
|
||||||
|
return collectionAuditTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCollectionAuditTable(CollectionAuditTable collectionAuditTable) {
|
||||||
|
this.collectionAuditTable = collectionAuditTable;
|
||||||
|
}
|
||||||
|
|
||||||
public PropertyData resolvePropertyData() {
|
public PropertyData resolvePropertyData() {
|
||||||
if ( propertyType != null && virtualPropertyType != null ) {
|
if ( propertyType != null && virtualPropertyType != null ) {
|
||||||
return new PropertyData(
|
return new PropertyData(
|
||||||
|
|
Loading…
Reference in New Issue