Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
272fdc1
[Enhancement #425] Add interfaces for basic entity graph support.
ledsoft Mar 2, 2026
d265f77
[Enhancement #425] Implementing entity graph model (WIP).
ledsoft Mar 2, 2026
b3b334b
[Enhancement #425] Extract entity describing query logic into a separ…
ledsoft Mar 18, 2026
4ed949a
[Enhancement #425] Recursively build SPARQL patterns from fetch graph.
ledsoft Mar 18, 2026
378a64b
[Enhancement #425] Reorder generated triple patterns - put OPTIONALs …
ledsoft Mar 18, 2026
279a97f
[Enhancement #425] Allow creating an EntityGraph via EM and pass it t…
ledsoft Mar 18, 2026
69aa489
[Enhancement #425] Use fetch graph to map query results to axioms.
ledsoft Mar 24, 2026
e6718f3
[Enhancement #425] Support extracting axioms for multiple entities fr…
ledsoft Mar 25, 2026
2afe3b8
[Enhancement #425] Pass fetch graph to entity loading from axioms.
ledsoft Mar 27, 2026
1312d6f
[Enhancement #425] Refactor axiom-based entity loading API.
ledsoft Mar 27, 2026
51865f1
[Enhancement #425] Minor simplification of ObjectOntologyMapperImpl.
ledsoft Mar 31, 2026
c707206
[Enhancement #425] Support loading entity graph from axioms by keepin…
ledsoft Mar 31, 2026
c2ca51b
[Enhancement #425] Pass fetch graph to entity construction.
ledsoft Apr 9, 2026
f92f867
[Enhancement #425] Use fetch graph when constructing entities.
ledsoft Apr 9, 2026
b517d96
[Enhancement #425] Add some integration tests for the fetch graph-bas…
ledsoft Apr 9, 2026
d34330c
[Enhancement #425] Use optimizer whenever fetch graph is provided to …
ledsoft Apr 10, 2026
f82a033
[Enhancement #425] Add some integration tests.
ledsoft Apr 10, 2026
21c35ef
[Enhancement #425] Allow QueryResultLoader to access relevant data fr…
ledsoft Apr 16, 2026
20381d8
[Enhancement #425] Use GROUP_CONCAT to prevent result row blowup for …
ledsoft Apr 17, 2026
583a11c
[Enhancement #425] Bind type in query optimizer when entity type has …
ledsoft Apr 21, 2026
33a539f
More robust lazy state resolution.
ledsoft Apr 22, 2026
aeca651
Validate integrity constraints only for loaded attributes.
ledsoft Apr 22, 2026
c7278a7
Synchronize resource creation in Jena OntoDriver tests to prevent con…
ledsoft Apr 30, 2026
6f6a43c
[Enhancement #425] Do not use group_concat to optimize entity referen…
ledsoft Apr 30, 2026
df9a169
[Ref] Refactor query result loading optimization.
ledsoft Apr 30, 2026
6f71562
[GH-429] Log prefix map reading on info level.
ledsoft Apr 30, 2026
cc5bbe2
[Enhancement #424] Do not require types projection when mapping query…
ledsoft May 4, 2026
1936ef8
[Enhancement #424] Add integration test for mapping query result with…
ledsoft May 4, 2026
ed225b5
[Bug #437] Add test reproducing the issue.
ledsoft May 15, 2026
bb9e262
[Bug #437] Pass statically declared descriptor to TypedQuery when ava…
ledsoft May 15, 2026
62e8a30
[Fix] Fix build hanging in Jena OntoDriver module tests.
ledsoft May 15, 2026
3011ee1
[Enhancement #434] Refactor group concat modification to allow more t…
ledsoft May 15, 2026
5e39179
[Enhancement #434] Use group_concat to optimize retrieval of multilin…
ledsoft May 15, 2026
929ca27
[Enhancement #434] Add integration test for multilingual string group…
ledsoft May 22, 2026
ab57dcb
Add explanatory comment to Jena tests environment initializer.
ledsoft May 22, 2026
4aae288
[Enhancement #434] Support plural string attribute group_concat.
ledsoft May 22, 2026
c5e210d
Cache maven dependencies in GH actions build.
ledsoft May 22, 2026
b659414
Add missing service declaration file for Jena driver tests.
ledsoft May 22, 2026
7fcafa0
[Enhancement #432] Support namespace mapping in PrefixMap
ledsoft May 19, 2026
1004a3e
[Enhancement #432] Resolve prefix based on resource IRI and not based…
ledsoft May 19, 2026
9dc62f8
[Enhancement #432] Introduce new config to separate forcing use of pr…
ledsoft May 19, 2026
9064e66
[Enhancement #432] Synchronize JOPA Maven plugin with updates in OWL2…
ledsoft May 19, 2026
d7645bc
[Enhancement #432] Generate ontology IRI vocabulary constant without …
ledsoft May 19, 2026
2b8e6df
[Enhancement #432] More consistent rules for constant naming in OWL2J…
ledsoft May 26, 2026
980eede
[Enhancement #432] Add SKOS to known ontologies
ledsoft May 26, 2026
73708aa
[Enhancement #432] Remove unused method in PrefixMap.
ledsoft May 26, 2026
5f89c78
[Enhancement #432] Add missing test ontology file.
ledsoft May 26, 2026
a16afe5
[Enhancement #431] Add annotations for declaring named entity graphs.
ledsoft May 26, 2026
06ac8e7
[Enhancement #431] Create basic infrastructure for processing named e…
ledsoft May 26, 2026
39a3b10
[Enhancement #431] Implement creation of EntityGraphs from NamedEntit…
ledsoft May 27, 2026
a5b2009
[Enhancement #431] Provide access to named entity graphs.
ledsoft May 27, 2026
0da652f
[Enhancement #431] Add integration tests for the feature.
ledsoft May 27, 2026
4cd1e76
[Fix] Fix javadoc error.
ledsoft May 28, 2026
4b31487
Eagerly initialize lazy loading proxy classes for all classes used in…
ledsoft May 28, 2026
7fece82
[GH-444] Do not use group_concat optimization when query has order by…
ledsoft May 28, 2026
8140719
[2.10.0] Bump version.
ledsoft May 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ jobs:
with:
distribution: 'temurin'
java-version: 17
cache: maven
- name: Build with Maven
run: mvn -P javadoc -B package --file pom.xml
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,5 @@ build.out
**/catalog-v001.xml
.project
.classpath
org.*
.factorypath
**/gen
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# JOPA - Change Log

### 2.10.0 - 2026-05-29

- Support optimizing entity loading from query result by using [fetch graphs](https://github.com/kbss-cvut/jopa/wiki/Performance#fetch-graph-based-entity-loading) (Enhancement #425, #431, #434).
- Implement more predictable naming strategy in OWL2Java (Enhancement #432) - see the [README](jopa-owl2java/README.md) for details.
- Ensure annotation-based entity descriptor is honored when loading entities from query result (Enhancement #437).
- Dependency updates: RDF4J 5.3.1.

### 2.9.4 - 2026-04-17

- Change return type of `CriteriaBuilder.langMatches` to `Predicate` to allow including it in predicate lists.
Expand Down
2 changes: 1 addition & 1 deletion datatype/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<artifactId>jopa-all</artifactId>
<groupId>cz.cvut.kbss.jopa</groupId>
<version>2.9.4</version>
<version>2.10.0</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion jopa-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>cz.cvut.kbss.jopa</groupId>
<artifactId>jopa-all</artifactId>
<version>2.9.4</version>
<version>2.10.0</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
25 changes: 25 additions & 0 deletions jopa-api/src/main/java/cz/cvut/kbss/jopa/model/AttributeNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package cz.cvut.kbss.jopa.model;

import java.util.Map;

/**
* Represents an attribute node of an entity graph.
*
* @param <T> The type of the attribute
*/
public interface AttributeNode<T> {

/**
* Gets the name of the attribute corresponding to the attribute node.
*
* @return name of the attribute
*/
String getAttributeName();

/**
* Return the map of subgraphs associated with this attribute node.
*
* @return Map of subgraphs associated with this attribute node or empty Map if none have been defined
*/
Map<Class, Subgraph> getSubgraphs();
}
108 changes: 108 additions & 0 deletions jopa-api/src/main/java/cz/cvut/kbss/jopa/model/EntityGraph.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package cz.cvut.kbss.jopa.model;

import cz.cvut.kbss.jopa.model.metamodel.Attribute;

import java.util.List;

/**
* This type represents the root of an entity graph that will be used as a template to define the attribute nodes and
* boundaries of a graph of entities and entity relationships.
* <p>
* The root must be an entity type.
* <p>
* The methods to add subgraphs implicitly create the corresponding attribute nodes as well; such attribute nodes should
* not be redundantly specified.
*
* @param <T> The type of the root entity
*/
public interface EntityGraph<T> {

/**
* Adds one or more attribute nodes to the entity graph.
*
* @param attribute Attribute to add
* @throws IllegalStateException If this {@code EntityGraph} has been statically defined
*/
void addAttributeNodes(Attribute<T, ?>... attribute);

/**
* Adds one or more attribute nodes to the entity graph.
*
* @param attributeName Name of the attribute to add
* @throws IllegalStateException If this {@code EntityGraph} has been statically defined
* @throws IllegalArgumentException If the attribute is not an attribute of this managed type
*/
void addAttributeNodes(String... attributeName);

/**
* Adds a node to the graph that corresponds to a managed type.
* <p>
* This allows for construction of multi-node entity graphs that include related managed types.
*
* @param attribute Attribute to add
* @param <X> Attribute type
* @return Subgraph for the attribute
* @throws IllegalStateException If this {@code EntityGraph} has been statically defined
* @throws IllegalArgumentException If the attribute's target type is not a managed type
*/
<X> Subgraph<X> addSubgraph(Attribute<T, X> attribute);

/**
* Adds a node to the graph that corresponds to a managed type.
* <p>
* This allows for construction of multi-node entity graphs that include related managed types.
*
* @param attributeName Name of the attribute to add
* @param <X> Attribute type
* @return Subgraph for the attribute
* @throws IllegalStateException If this {@code EntityGraph} has been statically defined
* @throws IllegalArgumentException If the attribute is not an attribute of this managed type
* @throws IllegalArgumentException If the attribute's target type is not a managed type
*/
<X> Subgraph<X> addSubgraph(String attributeName);

/**
* Adds a node to the graph that corresponds to a managed type with inheritance.
* <p>
* This allows for multiple subclass subgraphs to be defined for this node of the entity graph. Subclass subgraphs
* will automatically include the specified attributes of superclass subgraphs.
*
* @param attribute Attribute to add
* @param cls Entity subclass
* @param <X> Attribute type
* @return Subgraph for the attribute
* @throws IllegalStateException If this {@code EntityGraph} has been statically defined
* @throws IllegalArgumentException If the attribute's target type is not a managed type
*/
<X> Subgraph<? extends X> addSubgraph(Attribute<T, X> attribute, Class<? extends X> cls);

/**
* Add additional attributes to this entity graph that correspond to attributes of subclasses of this EntityGraph's
* entity type.
* <p>
* Subclass subgraphs will automatically include the specified attributes of superclass subgraphs.
*
* @param cls Entity subclass
* @return Subgraph for the subclass
* @throws IllegalStateException If this {@code EntityGraph} has been statically defined
* @throws IllegalArgumentException If the type is not a managed type
*/
Subgraph<? extends T> addSubclassSubgraph(Class<? extends T> cls);

/**
* Gets the attribute nodes corresponding to the attributes of this managed type that are included in the subgraph.
*
* @return List of attribute nodes included in the subgraph or empty list if none have been defined
*/
List<AttributeNode<?>> getAttributeNodes();

/**
* Gets the name of a named EntityGraph (an entity graph defined by means of the NamedEntityGraph annotation, or
* added by means of the addNamedEntityGraph method).
* <p>
* Returns null if the EntityGraph is not a named EntityGraph.
*
* @return Entity graph name, {@code null} if it is not named
*/
String getName();
}
20 changes: 20 additions & 0 deletions jopa-api/src/main/java/cz/cvut/kbss/jopa/model/EntityManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,26 @@ public interface EntityManager extends AutoCloseable {
*/
Query createNativeQuery(String sparqlString, String resultSetMapping);

/**
* Returns a mutable {@link EntityGraph} that can be used to dynamically create an entity graph.
*
* @param rootType Entity class
* @param <T> Root entity class type
* @return Entity graph
*/
<T> EntityGraph<T> createEntityGraph(Class<T> rootType);

/**
* Obtain a named {@link EntityGraph}.
* <p>
* The returned instance of EntityGraph should be considered immutable.
*
* @param graphName Name of an existing entity graph
* @return Named entity graph
* @throws IllegalArgumentException If there is no entity graph with the specified name
*/
EntityGraph<?> getEntityGraph(String graphName);

/**
* Return an object of the specified type to allow access to the provider-specific API. If the provider's
* EntityManager implementation does not support the specified class, the {@link OWLPersistenceException} is
Expand Down
88 changes: 88 additions & 0 deletions jopa-api/src/main/java/cz/cvut/kbss/jopa/model/Subgraph.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package cz.cvut.kbss.jopa.model;

import cz.cvut.kbss.jopa.model.metamodel.Attribute;

import java.util.List;

/**
* This type represents a subgraph for an attribute node that corresponds to a Managed Type.
* <p>
* Using this class, an entity subgraph can be embedded within an EntityGraph.
*
* @param <T> The type of the attribute
*/
public interface Subgraph<T> {

/**
* Adds one or more attribute nodes to the entity graph.
*
* @param attribute Attribute to add
* @throws IllegalStateException If this {@code EntityGraph} has been statically defined
*/
void addAttributeNodes(Attribute<T, ?>... attribute);

/**
* Adds one or more attribute nodes to the entity graph.
*
* @param attributeName Name of the attribute to add
* @throws IllegalStateException If this {@code EntityGraph} has been statically defined
* @throws IllegalArgumentException If the attribute is not an attribute of this managed type
*/
void addAttributeNodes(String... attributeName);

/**
* Adds a node to the graph that corresponds to a managed type.
* <p>
* This allows for construction of multi-node entity graphs that include related managed types.
*
* @param attribute Attribute to add
* @param <X> Attribute type
* @return Subgraph for the attribute
* @throws IllegalStateException If this {@code EntityGraph} has been statically defined
* @throws IllegalArgumentException If the attribute's target type is not a managed type
*/
<X> Subgraph<X> addSubgraph(Attribute<T, X> attribute);

/**
* Adds a node to the graph that corresponds to a managed type.
* <p>
* This allows for construction of multi-node entity graphs that include related managed types.
*
* @param attributeName Name of the attribute to add
* @param <X> Attribute type
* @return Subgraph for the attribute
* @throws IllegalStateException If this {@code EntityGraph} has been statically defined
* @throws IllegalArgumentException If the attribute is not an attribute of this managed type
* @throws IllegalArgumentException If the attribute's target type is not a managed type
*/
<X> Subgraph<X> addSubgraph(String attributeName);

/**
* Adds a node to the graph that corresponds to a managed type with inheritance.
* <p>
* This allows for multiple subclass subgraphs to be defined for this node of the entity graph. Subclass subgraphs
* will automatically include the specified attributes of superclass subgraphs.
*
* @param attribute Attribute to add
* @param cls Entity subclass
* @param <X> Attribute type
* @return Subgraph for the attribute
* @throws IllegalStateException If this {@code EntityGraph} has been statically defined
* @throws IllegalArgumentException If the attribute's target type is not a managed type
*/
<X> Subgraph<? extends X> addSubgraph(Attribute<T, X> attribute, Class<? extends X> cls);

/**
* Gets the attribute nodes corresponding to the attributes of this managed type that are included in the subgraph.
*
* @return List of attribute nodes included in the subgraph or empty list if none have been defined
*/
List<AttributeNode<?>> getAttributeNodes();

/**
* Gets the type for which this subgraph was defined.
*
* @return managed type referenced by the subgraph
*/
Class<T> getClassType();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package cz.cvut.kbss.jopa.model.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
* A NamedAttributeNode is a member element of a {@link NamedEntityGraph}.
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface NamedAttributeNode {

/**
* (Required) The name of the attribute that must be included in the graph.
*/
String value();

/**
* (Optional) If the attribute references a managed type that has its own AttributeNodes, this element is used to
* refer to that {@link NamedSubgraph} definition.
* <p>
* If the target type has inheritance, multiple subgraphs can be specified.These additional subgraphs are intended
* to add subclass-specific attributes. Superclass subgraph entries will be merged into subclass subgraphs.
* <p>
* The value of this element is the name of the subgraph as specified by the name element of the corresponding
* NamedSubgraph element. If multiple subgraphs are specified due to inheritance, they are referenced by this name.
*/
String subgraph() default "";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package cz.cvut.kbss.jopa.model.annotations;

import cz.cvut.kbss.jopa.model.EntityManager;

import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Defines a named entity graph.
* <p>
* This annotation must be applied to the root entity of the graph, and specifies the limits of the graph of associated
* attributes and entities fetched when an operation which retrieves an instance or instances of the root entity is
* executed.
* <p>
* A reference to a named entity graph may be obtained by calling {@link EntityManager#getEntityGraph(String)}, and may
* be passed as hint to {@link cz.cvut.kbss.jopa.model.query.TypedQuery}.
*/
@Repeatable(NamedEntityGraphs.class)
@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface NamedEntityGraph {

/**
* (Optional) The name used to identify the entity graph in calls to {@link EntityManager#getEntityGraph(String)}.
* <p>
* If no name is explicitly specified, the name defaults to the entity name of the annotated root entity. Entity
* graph names must be unique within the persistence unit.
*/
String name() default "";

/**
* (Optional) A list of attributes of the entity that are included in this graph.
*/
NamedAttributeNode[] attributeNodes() default {};

/**
* (Optional) Includes all the attributes of the annotated entity class as attribute nodes in the
* {@code NamedEntityGraph} without the need to explicitly list them.
* <p>
* Included attributes can still be fully specified by an attribute node referencing a subgraph.
*/
boolean includeAllAttributes() default false;

/**
* (Optional) A list of subgraphs that are included in the entity graph.
* <p>
* These are referenced by name from {@code NamedAttributeNode} definitions.
*/
NamedSubgraph[] subgraphs() default {};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package cz.cvut.kbss.jopa.model.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Used to group {@link NamedEntityGraph} annotations.
*/
@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface NamedEntityGraphs {

NamedEntityGraph[] value();
}
Loading