- Jmix-Framework:
2.8.2 - Jmix Studio:
3.0.0-261 - Idea 2026.1.3 Ultimate
Saving an entity instance which is designed by two nested mapped superclasses fails. The code looks like supporting it, but it actually does not return the ancestor of the ancestor.
appid_BaseEntityis a mapped super class entity and defines the primary key attribute, version etc.appid_LinkedBaseEntityis a mapped super itself and extendsappid_BaseEntity. It defines a foreign key to another entityappid_DataEntity1extendsLinkedBaseEntitywith further specific attributes
When creating a appid_DataEntity1 instance by using the DataManager without discard saving context, there is a reload attempt after saving. It tries to resolve the primary key attribute by meta classes.
java.lang.IllegalStateException: Entity appid_DataEntity1 has no primary key
at io.jmix.data.impl.JpqlQueryBuilder.getPrimaryKeyProperty(JpqlQueryBuilder.java:391) ~[jmix-data-2.8.2.jar:na]
at io.jmix.data.impl.JpqlQueryBuilder.buildResultQuery(JpqlQueryBuilder.java:223) ~[jmix-data-2.8.2.jar:na]
at io.jmix.data.impl.JpqlQueryBuilder.getResultQueryString(JpqlQueryBuilder.java:171) ~[jmix-data-2.8.2.jar:na]
at io.jmix.data.impl.JpqlQueryBuilder.getQuery(JpqlQueryBuilder.java:184) ~[jmix-data-2.8.2.jar:na]
at io.jmix.eclipselink.impl.JpaDataStore.createQuery(JpaDataStore.java:603) ~[jmix-eclipselink-2.8.2.jar:na]
at io.jmix.eclipselink.impl.JpaDataStore.loadOne(JpaDataStore.java:149) ~[jmix-eclipselink-2.8.2.jar:na]
at io.jmix.core.datastore.AbstractDataStore.loadAllAfterSave(AbstractDataStore.java:443) ~[jmix-core-2.8.2.jar:na]
at io.jmix.core.datastore.AbstractDataStore.save(AbstractDataStore.java:239) ~[jmix-core-2.8.2.jar:na]
at io.jmix.eclipselink.impl.JpaDataStore.save(JpaDataStore.java:244) ~[jmix-eclipselink-2.8.2.jar:na]
at io.jmix.core.impl.UnconstrainedDataManagerImpl.lambda$saveContextToStore$7(UnconstrainedDataManagerImpl.java:280) ~[jmix-core-2.8.2.jar:na]
at io.micrometer.observation.Observation.observe(Observation.java:564) ~[micrometer-observation-1.15.11.jar:1.15.11]
at io.jmix.core.impl.UnconstrainedDataManagerImpl.saveContextToStore(UnconstrainedDataManagerImpl.java:280) ~[jmix-core-2.8.2.jar:na]
at io.jmix.core.impl.UnconstrainedDataManagerImpl.save(UnconstrainedDataManagerImpl.java:237) ~[jmix-core-2.8.2.jar:na]
at io.jmix.core.impl.UnconstrainedDataManagerImpl.save(UnconstrainedDataManagerImpl.java:156) ~[jmix-core-2.8.2.jar:na]
I debugged it to MetadataTools line 246 (ancestor = ancestor.getAncestor();) returning null.
@Nullable
public String getPrimaryKeyName(MetaClass metaClass) {
String pkProperty = (String) metaClass.getAnnotations().get(PRIMARY_KEY_ANN_NAME);
if (pkProperty != null) {
return pkProperty;
} else {
MetaClass ancestor = metaClass.getAncestor();
while (ancestor != null) {
pkProperty = (String) ancestor.getAnnotations().get(PRIMARY_KEY_ANN_NAME);
if (pkProperty != null)
return pkProperty;
ancestor = ancestor.getAncestor();
}
}
return null;
}