hibernate/hibernate-orm · error · MappingException

The @Changelog entity cannot be audited

Error message

The @Changelog entity cannot be audited

What it means

Hibernate 7's built-in changelog/audit mechanism (org.hibernate.annotations.Changelog) turns the annotated entity into the changeset log that RECORDS audits for other entities; it must therefore never itself be the target of auditing. Binding fails with a MappingException when the @Changelog entity also carries '@Audited'.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/AuditHelper.java:410

		else {
			final String ownerSimpleName = collection.getOwner().getJpaEntityName();
			final String childSimpleName = referencedEntity.getJpaEntityName();
			return ownerSimpleName + "_" + childSimpleName + DEFAULT_TABLE_SUFFIX;
		}
	}

	static void bindChangelog(
			Changelog changelog,
			RootClass rootClass,
			ClassDetails classDetails,
			MetadataBuildingContext context) {
		final var modelsContext = context.getBootstrapContext().getModelsContext();

		// note : @Changelog currently requires @Entity as well

		// The entity must not be audited
		if ( classDetails.hasAnnotationUsage( Audited.class, modelsContext ) ) {
			throw new MappingException( "The @Changelog entity cannot be audited" );
		}

		// Scan class members (including supertypes) for @ChangesetId,
		// @Timestamp, and @ModifiedEntities. We need the names
		// and type eagerly to configure the supplier before audit table
		// second passes create the REV column.
		MemberDetails revNumberMember = null;
		MemberDetails revTimestampMember = null;
		MemberDetails modifiedEntityNamesMember = null;
		for ( var current = classDetails; current != null; current = current.getSuperClass() ) {
			for ( var member : current.getFields() ) {
				revNumberMember = checkAnnotation(
						member,
						revNumberMember,
						Changelog.ChangesetId.class,
						classDetails
				);
				revTimestampMember = checkAnnotation(

View on GitHub (pinned to fad1729dce)

Solutions

  1. Remove '@Audited' from the @Changelog entity named in the message.
  2. If using global audit-everywhere configuration, exclude the changelog entity from that default.
  3. Verify @Changelog is only on the dedicated changeset entity, not on regular business entities.

Example fix

// before
@Audited            // -> MappingException
@Changelog
@Entity
public class Changeset {
    @Changelog.ChangesetId Long id;
    @Changelog.Timestamp Instant at;
}

// after
@Changelog
@Entity
public class Changeset {
    @Changelog.ChangesetId Long id;
    @Changelog.Timestamp Instant at;
}
Defensive patterns

Strategy: validation

Validate before calling

// Guard: changelog entities must not be audited
if (cls.isAnnotationPresent(Changelog.class) && cls.isAnnotationPresent(Audited.class)) {
    throw new IllegalStateException(
        cls.getName() + ": @Changelog entity must not be @Audited");
}

Try / catch

try {
    factory = cfg.buildSessionFactory();
} catch (MappingException e) {
    // 'The @Changelog entity cannot be audited' -> remove @Audited from the
    // changelog entity
    throw newConfigurationException("Changelog misconfiguration", e);
}

Prevention

When it happens

Trigger: A class annotated '@Changelog' (a changeset entity with @Changelog.ChangesetId, @Changelog.Timestamp and optionally @Changelog.ModifiedEntities members) that is also annotated '@Audited'; reusing an old Envers revision entity and adding @Audited 'for consistency'; audit-everything tooling that stamps @Audited on all entities including the changelog.

Common situations: Migrating from Envers '@RevisionEntity' to the native @Changelog and leaving @Audited on; team policies that audit all entities automatically; experimenting with the new audit API on an already-audited type.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/f9fd41a1b4547f58. Report an issue: GitHub.