diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 8cafaa3d4..6ad2b4db7 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -12,9 +12,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
- name: Set up JDK
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: 17
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b6a9944f3..a5b0f03a1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# JOPA - Change Log
+### 2.9.4 - 2026-04-17
+
+- Change return type of `CriteriaBuilder.langMatches` to `Predicate` to allow including it in predicate lists.
+- Fix an issue with instances of subclasses of parents containing inferred attributes not being evicted from cache after
+ transaction commit.
+- Dependency updates: RDF4J 5.3.0.
+
### 2.9.3 - 2026-03-16
- Fix driver-level transaction not being started when JOPA transaction starts with a query (Bug #426).
@@ -53,8 +60,10 @@
- Support entity classes with subclasses by the entity loading optimizer (Enhancement #357).
- Support entity loading optimization in query result stream (Enhancement #357).
-- Always resolve the most specific entity classes for instantiation (instead of preferring class exactly matching the requested type).
-- Eagerly generate lazy loading entity proxy classes for entity classes that are actually referenced by attributes with fetchType=LAZY in the model (Enhancement #380).
+- Always resolve the most specific entity classes for instantiation (instead of preferring class exactly matching the
+ requested type).
+- Eagerly generate lazy loading entity proxy classes for entity classes that are actually referenced by attributes with
+ fetchType=LAZY in the model (Enhancement #380).
- Dependency updates: Jena 5.6.0.
### 2.6.3 - 2025-10-07
diff --git a/datatype/pom.xml b/datatype/pom.xml
index a3503f297..a38f766a4 100644
--- a/datatype/pom.xml
+++ b/datatype/pom.xml
@@ -6,7 +6,7 @@
jopa-all
cz.cvut.kbss.jopa
- 2.9.3
+ 2.9.4
../pom.xml
diff --git a/jopa-api/pom.xml b/jopa-api/pom.xml
index 5453dfe19..295e01174 100644
--- a/jopa-api/pom.xml
+++ b/jopa-api/pom.xml
@@ -6,7 +6,7 @@
cz.cvut.kbss.jopa
jopa-all
- 2.9.3
+ 2.9.4
../pom.xml
diff --git a/jopa-api/src/main/java/cz/cvut/kbss/jopa/model/query/criteria/CriteriaBuilder.java b/jopa-api/src/main/java/cz/cvut/kbss/jopa/model/query/criteria/CriteriaBuilder.java
index b4a85f255..55e6cf8ef 100644
--- a/jopa-api/src/main/java/cz/cvut/kbss/jopa/model/query/criteria/CriteriaBuilder.java
+++ b/jopa-api/src/main/java/cz/cvut/kbss/jopa/model/query/criteria/CriteriaBuilder.java
@@ -138,7 +138,7 @@ public interface CriteriaBuilder extends PredicateFactory {
* @param range Language range expression
* @return Function call expression
*/
- Expression langMatches(Expression value, Expression range);
+ Predicate langMatches(Expression value, Expression range);
/**
* Creates an expression for checking if the specified value matches the specified language range.
@@ -147,7 +147,7 @@ public interface CriteriaBuilder extends PredicateFactory {
* @param range Language range literal
* @return Function call expression
*/
- Expression langMatches(Expression value, String range);
+ Predicate langMatches(Expression value, String range);
/**
* Create an ordering by the ascending value of the expression.
diff --git a/jopa-distribution/pom.xml b/jopa-distribution/pom.xml
index 1ac81b722..2009c9c66 100644
--- a/jopa-distribution/pom.xml
+++ b/jopa-distribution/pom.xml
@@ -6,7 +6,7 @@
cz.cvut.kbss.jopa
jopa-all
- 2.9.3
+ 2.9.4
../pom.xml
diff --git a/jopa-impl/pom.xml b/jopa-impl/pom.xml
index d4231b6af..f74296bf7 100644
--- a/jopa-impl/pom.xml
+++ b/jopa-impl/pom.xml
@@ -6,7 +6,7 @@
cz.cvut.kbss.jopa
jopa-all
- 2.9.3
+ 2.9.4
../pom.xml
diff --git a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/model/metamodel/MetamodelBuilder.java b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/model/metamodel/MetamodelBuilder.java
index c576f1fc2..0ed5b0da9 100644
--- a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/model/metamodel/MetamodelBuilder.java
+++ b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/model/metamodel/MetamodelBuilder.java
@@ -155,17 +155,13 @@ private void processManagedType(TypeBuilderContext context) {
fieldProcessor.processField(f);
}
- if (!type.isAbstract()) {
- try {
- type.getIdentifier();
- } catch (IllegalArgumentException e) {
- throw new MetamodelInitializationException("Missing identifier field in entity " + cls);
- }
- }
-
+ verifyIdentifierPresence(type);
if (type.getPersistenceType() == Type.PersistenceType.ENTITY) {
resolveInheritanceType((IdentifiableEntityType) type);
}
+ if (supertypes.stream().anyMatch(st -> inferredClasses.contains(st.getJavaType()))) {
+ addInferredClass(cls);
+ }
queryProcessor.processClass(cls);
}
@@ -195,6 +191,16 @@ private Set> processSupertypes(Class
return superTypes;
}
+ private static void verifyIdentifierPresence(AbstractIdentifiableType type) {
+ if (!type.isAbstract()) {
+ try {
+ type.getIdentifier();
+ } catch (IllegalArgumentException e) {
+ throw new MetamodelInitializationException("Missing identifier field in entity " + type.getJavaType());
+ }
+ }
+ }
+
private static boolean canDeclareInheritanceStrategy(IdentifiableType et) {
return et.getSupertypes() == null || et.getSupertypes()
.stream()
diff --git a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/criteria/CriteriaBuilderImpl.java b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/criteria/CriteriaBuilderImpl.java
index d0ebdb485..34cc8b744 100644
--- a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/criteria/CriteriaBuilderImpl.java
+++ b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/criteria/CriteriaBuilderImpl.java
@@ -153,12 +153,12 @@ public Expression lang(Path x) {
}
@Override
- public Expression langMatches(Expression value, Expression range) {
- return new LangMatchesFunction(this, (AbstractExpression) value, (AbstractExpression) range);
+ public Predicate langMatches(Expression value, Expression range) {
+ return new SimplePredicateImpl(new LangMatchesFunction(this, (AbstractExpression) value, (AbstractExpression) range), this);
}
@Override
- public Expression langMatches(Expression value, String range) {
+ public Predicate langMatches(Expression value, String range) {
return langMatches(value, new ExpressionLiteralImpl<>(range, this));
}
diff --git a/jopa-impl/src/test/java/cz/cvut/kbss/jopa/model/metamodel/MetamodelBuilderTest.java b/jopa-impl/src/test/java/cz/cvut/kbss/jopa/model/metamodel/MetamodelBuilderTest.java
index 5b4e2ea5f..ed7679eed 100644
--- a/jopa-impl/src/test/java/cz/cvut/kbss/jopa/model/metamodel/MetamodelBuilderTest.java
+++ b/jopa-impl/src/test/java/cz/cvut/kbss/jopa/model/metamodel/MetamodelBuilderTest.java
@@ -80,6 +80,7 @@
import static org.hamcrest.CoreMatchers.containsStringIgnoringCase;
import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
@@ -757,4 +758,27 @@ public static class ClassWithLazySingularAttribute {
@OWLObjectProperty(iri = Vocabulary.ATTRIBUTE_BASE + "lazyAttribute", fetch = FetchType.LAZY)
private OWLClassA lazyAttribute;
}
+
+ @Test
+ void buildMetamodelIncludesSubtypesOfMappedSuperclassWithInferredAttributeInInferredClasses() {
+ when(finderMock.getEntities()).thenReturn(Set.of(MappedSuperclassWithInferredAttribute.class, SubClassWithInferredParent.class));
+ builder.buildMetamodel(finderMock);
+ assertThat(builder.getInferredClasses(), hasItems(MappedSuperclassWithInferredAttribute.class, SubClassWithInferredParent.class));
+ }
+
+ @TestLocal
+ @MappedSuperclass
+ public static class MappedSuperclassWithInferredAttribute {
+ @Id
+ private URI id;
+
+ @Inferred
+ @OWLObjectProperty(iri = Vocabulary.ATTRIBUTE_BASE + "parentInferredAttribute")
+ private URI parentInferredAttribute;
+ }
+
+ @TestLocal
+ @OWLClass(iri = Vocabulary.CLASS_BASE + "SubClassWithInferredParent")
+ public static class SubClassWithInferredParent extends MappedSuperclassWithInferredAttribute {
+ }
}
diff --git a/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/criteria/CriteriaQueryTranslateQueryTest.java b/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/criteria/CriteriaQueryTranslateQueryTest.java
index 542fe2cc3..30c5c2be6 100644
--- a/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/criteria/CriteriaQueryTranslateQueryTest.java
+++ b/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/criteria/CriteriaQueryTranslateQueryTest.java
@@ -147,6 +147,18 @@ void translateQuerySupportsLangMatches() {
assertEquals(expectedSoqlQuery, generatedSoqlQuery);
}
+ @Test
+ void translateQuerySupportsLangMatchesInListOfRestrictions() {
+ CriteriaQueryImpl query = cb.createQuery(OWLClassA.class);
+ Root root = query.from(OWLClassA.class);
+ final List restrictions = List.of(cb.langMatches(root.getAttr("stringAttribute"), "en"));
+ query.select(root).where(restrictions);
+
+ final String generatedSoqlQuery = query.translateQuery(criteriaParameterFiller);
+ final String expectedSoqlQuery = "SELECT owlclassa FROM OWLClassA owlclassa WHERE LANGMATCHES(owlclassa.stringAttribute, :generatedName0)";
+ assertEquals(expectedSoqlQuery, generatedSoqlQuery);
+ }
+
@Test
void translateQuerySupportsSelectionByIdentifierInParameter() {
CriteriaQueryImpl query = cb.createQuery(OWLClassM.class);
diff --git a/jopa-integration-tests-jena/pom.xml b/jopa-integration-tests-jena/pom.xml
index eb74cac73..bbb68a512 100644
--- a/jopa-integration-tests-jena/pom.xml
+++ b/jopa-integration-tests-jena/pom.xml
@@ -5,7 +5,7 @@
cz.cvut.kbss.jopa
jopa-all
- 2.9.3
+ 2.9.4
../pom.xml
4.0.0
diff --git a/jopa-integration-tests-owlapi/pom.xml b/jopa-integration-tests-owlapi/pom.xml
index 3289515a5..a091e97bb 100644
--- a/jopa-integration-tests-owlapi/pom.xml
+++ b/jopa-integration-tests-owlapi/pom.xml
@@ -5,7 +5,7 @@
cz.cvut.kbss.jopa
jopa-all
- 2.9.3
+ 2.9.4
../pom.xml
4.0.0
diff --git a/jopa-integration-tests-rdf4j/pom.xml b/jopa-integration-tests-rdf4j/pom.xml
index 464eecac0..0bf6b1496 100644
--- a/jopa-integration-tests-rdf4j/pom.xml
+++ b/jopa-integration-tests-rdf4j/pom.xml
@@ -6,7 +6,7 @@
cz.cvut.kbss.jopa
jopa-all
- 2.9.3
+ 2.9.4
../pom.xml
jopa-integration-tests-rdf4j
diff --git a/jopa-integration-tests-virtuoso/pom.xml b/jopa-integration-tests-virtuoso/pom.xml
index 4943be421..0b858e2c1 100644
--- a/jopa-integration-tests-virtuoso/pom.xml
+++ b/jopa-integration-tests-virtuoso/pom.xml
@@ -6,7 +6,7 @@
cz.cvut.kbss.jopa
jopa-all
- 2.9.3
+ 2.9.4
jopa-integration-tests-virtuoso
diff --git a/jopa-integration-tests/pom.xml b/jopa-integration-tests/pom.xml
index df88fbfd5..92cfb0d90 100644
--- a/jopa-integration-tests/pom.xml
+++ b/jopa-integration-tests/pom.xml
@@ -6,7 +6,7 @@
cz.cvut.kbss.jopa
jopa-all
- 2.9.3
+ 2.9.4
../pom.xml
4.0.0
diff --git a/jopa-maven-plugin/pom.xml b/jopa-maven-plugin/pom.xml
index 828e06a7b..156c57b66 100644
--- a/jopa-maven-plugin/pom.xml
+++ b/jopa-maven-plugin/pom.xml
@@ -5,7 +5,7 @@
jopa-all
cz.cvut.kbss.jopa
- 2.9.3
+ 2.9.4
../pom.xml
4.0.0
diff --git a/jopa-owl2java/pom.xml b/jopa-owl2java/pom.xml
index ad420bd33..809e41555 100644
--- a/jopa-owl2java/pom.xml
+++ b/jopa-owl2java/pom.xml
@@ -6,7 +6,7 @@
cz.cvut.kbss.jopa
jopa-all
- 2.9.3
+ 2.9.4
../pom.xml
diff --git a/jopa-owlapi-utils/pom.xml b/jopa-owlapi-utils/pom.xml
index 294ff5153..d6e97a42d 100644
--- a/jopa-owlapi-utils/pom.xml
+++ b/jopa-owlapi-utils/pom.xml
@@ -6,7 +6,7 @@
cz.cvut.kbss.jopa
jopa-all
- 2.9.3
+ 2.9.4
../pom.xml
diff --git a/modelgen/pom.xml b/modelgen/pom.xml
index c93cf6c7d..53ed75dda 100644
--- a/modelgen/pom.xml
+++ b/modelgen/pom.xml
@@ -6,7 +6,7 @@
jopa-all
cz.cvut.kbss.jopa
- 2.9.3
+ 2.9.4
../pom.xml
diff --git a/ontodriver-api/pom.xml b/ontodriver-api/pom.xml
index 18f46529a..0c54de62c 100644
--- a/ontodriver-api/pom.xml
+++ b/ontodriver-api/pom.xml
@@ -6,7 +6,7 @@
jopa-all
cz.cvut.kbss.jopa
- 2.9.3
+ 2.9.4
../pom.xml
diff --git a/ontodriver-jena/pom.xml b/ontodriver-jena/pom.xml
index f8ae1a67f..f13e29357 100644
--- a/ontodriver-jena/pom.xml
+++ b/ontodriver-jena/pom.xml
@@ -8,7 +8,7 @@
cz.cvut.kbss.jopa
jopa-all
- 2.9.3
+ 2.9.4
../pom.xml
diff --git a/ontodriver-owlapi/pom.xml b/ontodriver-owlapi/pom.xml
index 1e74011fd..7ff0213e5 100644
--- a/ontodriver-owlapi/pom.xml
+++ b/ontodriver-owlapi/pom.xml
@@ -11,7 +11,7 @@
cz.cvut.kbss.jopa
jopa-all
- 2.9.3
+ 2.9.4
../pom.xml
diff --git a/ontodriver-rdf4j/pom.xml b/ontodriver-rdf4j/pom.xml
index b159ae42d..fc04f00e3 100644
--- a/ontodriver-rdf4j/pom.xml
+++ b/ontodriver-rdf4j/pom.xml
@@ -10,11 +10,11 @@
jopa-all
cz.cvut.kbss.jopa
- 2.9.3
+ 2.9.4
- 5.2.2
+ 5.3.0
diff --git a/ontodriver-virtuoso/pom.xml b/ontodriver-virtuoso/pom.xml
index 1b615f3cb..077d34210 100644
--- a/ontodriver-virtuoso/pom.xml
+++ b/ontodriver-virtuoso/pom.xml
@@ -6,7 +6,7 @@
cz.cvut.kbss.jopa
jopa-all
- 2.9.3
+ 2.9.4
ontodriver-virtuoso
diff --git a/pom.xml b/pom.xml
index b230db2b7..1ef892312 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
cz.cvut.kbss.jopa
- 2.9.3
+ 2.9.4
jopa-all
pom
JOPA
@@ -44,7 +44,7 @@
2.0.17
6.0.2
5.21.0
- 1.5.26
+ 1.5.32
5.5.1