hibernate/hibernate-orm · error · PropertyNotFoundException

Could not resolve attribute '${name}' of any mapping (must b

Error message

Could not resolve attribute '${name}' of any mapping (must be one of 'class', 'id')

What it means

AnyType.getPropertyIndex (AnyType.java:394) only knows the two synthetic sub-attributes of an @Any mapping: 'class' (the discriminator) and 'id' (the foreign key). Any other attribute name asked for on an any-typed path throws PropertyNotFoundException with this message, listing the two legal names.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/AnyType.java:402

	}

	private static final String[] PROPERTY_NAMES = new String[] { "class", "id" };

	@Override
	public String[] getPropertyNames() {
		return PROPERTY_NAMES;
	}

	@Override
	public int getPropertyIndex(String name) {
		if ( PROPERTY_NAMES[0].equals( name ) ) {
			return 0;
		}
		else if ( PROPERTY_NAMES[1].equals( name ) ) {
			return 1;
		}

		throw new PropertyNotFoundException( "Could not resolve attribute '" + name
				+ "' of any mapping (must be one of 'class', 'id')" );
	}

	@Override
	public Object getPropertyValue(Object component, int i, SharedSessionContractImplementor session) throws HibernateException {
		return i==0
				? session.bestGuessEntityName( component )
				: getIdentifier( component, session );
	}

	@Override
	public Object[] getPropertyValues(Object component, SharedSessionContractImplementor session) throws HibernateException {
		return new Object[] {
				session.bestGuessEntityName( component ),
				getIdentifier( component, session )
		};
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Query only the two valid sub-attributes: compare the discriminator ('class') and the id, e.g. 'where d.owner.class = User and d.owner.id = :id' (or type(...) checks per HQL dialect support).
  2. If you need to filter by fields of the target entity, load the target by the stored (class, id) pair in a second query or restructure to @ManyToOne so real joins are possible.
  3. Regenerate derived queries after changing an association from @ManyToOne to @Any.

Example fix

// before (owner is @Any)
List<Doc> docs = session.createQuery(
    "from Doc d where d.owner.name = :n", Doc.class)
    .setParameter("n", "alice")
    .getResultList();

// after: constrain via discriminator + id, then load targets
List<Doc> docs = session.createQuery(
    "from Doc d where d.owner.class = User and d.owner.id = :uid", Doc.class)
    .setParameter("uid", aliceId)
    .getResultList();
Defensive patterns

Strategy: validation

Validate before calling

// Validate an attribute path against the metamodel before running HQL
static void checkPath(Metamodel mm, Class<?> root, String... path) {
    Bindable<?> b = mm.entity(root);
    for (String name : path) {
        Attribute<?, ?> a = ((ManagedType<?>) b).getAttribute(name); // throws IllegalArgumentException early
        b = (a instanceof SingularAttribute<?, ?> sa) ? sa.getType() : null;
    }
}
checkPath(mm, Doc.class, "owner", "id"); // ok for @Any; "name" would fail with a clear message

Type guard

static boolean isAnyMapped(Attribute<?, ?> attr) {
    return attr.getJavaMember() instanceof Field f
        && (f.isAnnotationPresent(Any.class) || f.isAnnotationPresent(ManyToAny.class));
}

Try / catch

try {
    return session.createQuery(jpql, Doc.class).getResultList();
} catch (IllegalArgumentException e) {
    if (e.getCause() instanceof PropertyNotFoundException pnfe
            && pnfe.getMessage().contains("of any mapping")) {
        throw new QueryValidationException(
            "Only 'class' and 'id' are queryable on an @Any attribute: " + jpql, e);
    }
    throw e;
}

Prevention

When it happens

Trigger: HQL/JPQL or Criteria that navigates into an @Any/@ManyToAny property with an attribute other than class or id, e.g. 'from Doc d where d.owner.name = :n' where owner is @Any; also programmatic calls to AnyType.getPropertyIndex(name), e.g. via property resolution APIs or reflection-based mapping validation.

Common situations: Developers treating @Any like a real entity association in queries; query generators that walk metamodel attributes uniformly and emit nested paths over any-typed members; refactoring a @ManyToOne to @Any and leaving old JPQL path expressions in place.

Related errors


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