22
33import java .util .Date ;
44import java .util .List ;
5+ import java .util .concurrent .Callable ;
56
67import javax .annotation .Nonnull ;
78import javax .annotation .Nullable ;
89
910import io .objectbox .Box ;
11+ import io .objectbox .BoxStore ;
12+ import io .objectbox .InternalAccess ;
1013import io .objectbox .Property ;
1114import io .objectbox .annotation .apihint .Beta ;
1215import io .objectbox .internal .CallWithHandle ;
1316import io .objectbox .reactive .DataObserver ;
1417import io .objectbox .reactive .SubscriptionBuilder ;
18+ import io .objectbox .relation .RelationInfo ;
19+ import io .objectbox .relation .ToOne ;
1520
1621/**
1722 * A repeatable query returning entities.
@@ -61,18 +66,22 @@ native static void nativeSetParameters(long handle, int propertyId, String param
6166 native static void nativeSetParameter (long handle , int propertyId , String parameterAlias , double value );
6267
6368 native static void nativeSetParameters (long handle , int propertyId , String parameterAlias , double value1 ,
64- double value2 );
69+ double value2 );
6570
6671 private final Box <T > box ;
72+ private final BoxStore store ;
6773 private final boolean hasOrder ;
68- long handle ;
6974 private final QueryPublisher <T > publisher ;
75+ private final List <EagerRelation > eagerRelations ;
76+ long handle ;
7077
71- Query (Box <T > box , long queryHandle , boolean hasOrder ) {
78+ Query (Box <T > box , long queryHandle , boolean hasOrder , List < EagerRelation > eagerRelations ) {
7279 this .box = box ;
80+ store = box .getStore ();
7381 handle = queryHandle ;
7482 this .hasOrder = hasOrder ;
7583 publisher = new QueryPublisher <>(this , box );
84+ this .eagerRelations = eagerRelations ;
7685 }
7786
7887 @ Override
@@ -96,10 +105,13 @@ public synchronized void close() {
96105 */
97106 @ Nullable
98107 public T findFirst () {
99- return box . internalCallWithReaderHandle (new CallWithHandle <T >() {
108+ return store . callInReadTx (new Callable <T >() {
100109 @ Override
101- public T call (long cursorHandle ) {
102- return (T ) nativeFindFirst (handle , cursorHandle );
110+ public T call () {
111+ @ SuppressWarnings ("unchecked" )
112+ T entity = (T ) nativeFindFirst (handle , InternalAccess .getActiveTxCursorHandle (box ));
113+ resolveEagerRelation (entity );
114+ return entity ;
103115 }
104116 });
105117 }
@@ -111,10 +123,13 @@ public T call(long cursorHandle) {
111123 */
112124 @ Nullable
113125 public T findUnique () {
114- return box . internalCallWithReaderHandle (new CallWithHandle <T >() {
126+ return store . callInReadTx (new Callable <T >() {
115127 @ Override
116- public T call (long cursorHandle ) {
117- return (T ) nativeFindUnique (handle , cursorHandle );
128+ public T call () {
129+ @ SuppressWarnings ("unchecked" )
130+ T entity = (T ) nativeFindUnique (handle , InternalAccess .getActiveTxCursorHandle (box ));
131+ resolveEagerRelation (entity );
132+ return entity ;
118133 }
119134 });
120135 }
@@ -124,10 +139,13 @@ public T call(long cursorHandle) {
124139 */
125140 @ Nonnull
126141 public List <T > find () {
127- return box . internalCallWithReaderHandle (new CallWithHandle <List <T >>() {
142+ return store . callInReadTx (new Callable <List <T >>() {
128143 @ Override
129- public List <T > call (long cursorHandle ) {
130- return nativeFind (handle , cursorHandle , 0 , 0 );
144+ public List <T > call () throws Exception {
145+ long cursorHandle = InternalAccess .getActiveTxCursorHandle (box );
146+ List entities = nativeFind (Query .this .handle , cursorHandle , 0 , 0 );
147+ resolveEagerRelations (entities );
148+ return entities ;
131149 }
132150 });
133151 }
@@ -137,10 +155,13 @@ public List<T> call(long cursorHandle) {
137155 */
138156 @ Nonnull
139157 public List <T > find (final long offset , final long limit ) {
140- return box . internalCallWithReaderHandle (new CallWithHandle <List <T >>() {
158+ return store . callInReadTx (new Callable <List <T >>() {
141159 @ Override
142- public List <T > call (long cursorHandle ) {
143- return nativeFind (handle , cursorHandle , offset , limit );
160+ public List <T > call () {
161+ long cursorHandle = InternalAccess .getActiveTxCursorHandle (box );
162+ List entities = nativeFind (handle , cursorHandle , offset , limit );
163+ resolveEagerRelations (entities );
164+ return entities ;
144165 }
145166 });
146167 }
@@ -185,11 +206,14 @@ public void run() {
185206 LazyList <T > lazyList = findLazy ();
186207 int size = lazyList .size ();
187208 for (int i = 0 ; i < size ; i ++) {
188- T data = lazyList .get (i );
189- if (data == null ) {
209+ T entity = lazyList .get (i );
210+ if (entity == null ) {
190211 throw new IllegalStateException ("Internal error: data object was null" );
191212 }
192- consumer .accept (data );
213+ if (eagerRelations != null ) {
214+ resolveEagerRelationForNonNullEagerRelations (entity , i );
215+ }
216+ consumer .accept (entity );
193217 }
194218 }
195219 });
@@ -203,6 +227,53 @@ public LazyList<T> findLazyCached() {
203227 return new LazyList <>(box , findIds (), true );
204228 }
205229
230+ void resolveEagerRelations (List entities ) {
231+ if (eagerRelations != null ) {
232+ int entityIndex = 0 ;
233+ for (Object entity : entities ) {
234+ resolveEagerRelationForNonNullEagerRelations (entity , entityIndex );
235+ entityIndex ++;
236+ }
237+ }
238+ }
239+
240+ /** Note: no null check on eagerRelations! */
241+ void resolveEagerRelationForNonNullEagerRelations (Object entity , int entityIndex ) {
242+ for (EagerRelation eagerRelation : eagerRelations ) {
243+ if (eagerRelation .limit == 0 || entityIndex < eagerRelation .limit ) {
244+ resolveEagerRelation (entity , eagerRelation );
245+ }
246+ }
247+ }
248+
249+ void resolveEagerRelation (Object entity ) {
250+ if (eagerRelations != null ) {
251+ for (EagerRelation eagerRelation : eagerRelations ) {
252+ resolveEagerRelation (entity , eagerRelation );
253+ }
254+ }
255+ }
256+
257+ void resolveEagerRelation (Object entity , EagerRelation eagerRelation ) {
258+ if (eagerRelations != null ) {
259+ RelationInfo relationInfo = eagerRelation .relationInfo ;
260+ if (relationInfo .toOneGetter != null ) {
261+ ToOne toOne = relationInfo .toOneGetter .getToOne (entity );
262+ if (toOne != null ) {
263+ toOne .getTarget ();
264+ }
265+ } else {
266+ if (relationInfo .toManyGetter == null ) {
267+ throw new IllegalStateException ("Relation info without relation getter: " + relationInfo );
268+ }
269+ List toMany = relationInfo .toManyGetter .getToMany (entity );
270+ if (toMany != null ) {
271+ toMany .size ();
272+ }
273+ }
274+ }
275+ }
276+
206277 /** Returns the count of Objects matching the query. */
207278 public long count () {
208279 return box .internalCallWithReaderHandle (new CallWithHandle <Long >() {
0 commit comments