3535import io .objectbox .BoxStore ;
3636import io .objectbox .Cursor ;
3737import io .objectbox .InternalAccess ;
38+ import io .objectbox .annotation .Backlink ;
3839import io .objectbox .annotation .apihint .Beta ;
3940import io .objectbox .annotation .apihint .Experimental ;
4041import io .objectbox .annotation .apihint .Internal ;
4344import io .objectbox .internal .ReflectionCache ;
4445import io .objectbox .internal .ToManyGetter ;
4546import io .objectbox .internal .ToOneGetter ;
47+ import io .objectbox .query .QueryBuilder ;
4648import io .objectbox .query .QueryFilter ;
4749import io .objectbox .relation .ListFactory .CopyOnWriteArrayListFactory ;
4850
4951import static java .lang .Boolean .TRUE ;
5052
5153/**
52- * A List representing a to-many relation.
53- * It tracks changes (adds and removes) that can be later applied (persisted) to the database.
54- * This happens either on {@link Box#put(Object)} of the source entity of this relation or using
55- * {@link #applyChangesToDb()}.
54+ * A lazily loaded {@link List} of target objects representing a to-many relation, a unidirectional link from a "source"
55+ * entity to multiple objects of a "target" entity.
5656 * <p>
57- * If this relation is a backlink from a {@link ToOne} relation, a DB sync will also update ToOne objects
58- * (but not vice versa).
57+ * It tracks changes (adds and removes) that can be later applied (persisted) to the database. This happens either when
58+ * the object that contains this relation is put or using {@link #applyChangesToDb()}. For some important details about
59+ * applying changes, see the notes about relations of {@link Box#put(Object)}.
5960 * <p>
60- * ToMany is thread-safe by default (only if the default {@link java.util.concurrent.CopyOnWriteArrayList} is used).
61+ * The objects are loaded lazily on first access of this list, and then cached. The database query runs on the calling
62+ * thread, so avoid accessing this from a UI or main thread. Subsequent calls to any method, like {@link #size()}, do
63+ * not query the database, even if the relation was changed elsewhere. To get the latest data {@link Box#get} the source
64+ * object again or use {@link #reset()} before accessing the list again.
65+ * <p>
66+ * It is possible to preload the list when running a query using {@link QueryBuilder#eager}.
67+ * <p>
68+ * ToMany is thread-safe by default (may not be the case if {@link #setListFactory(ListFactory)} is used).
6169 *
6270 * @param <TARGET> Object type (entity).
6371 */
@@ -482,8 +490,10 @@ public <T> T[] toArray(T[] array) {
482490 }
483491
484492 /**
485- * Resets the already loaded entities so they will be re-loaded on their next access.
486- * This allows to sync with non-tracked changes (outside of this ToMany object).
493+ * Resets the already loaded (cached) objects of this list, so they will be re-loaded when accessing this list
494+ * again.
495+ * <p>
496+ * Use this to sync with changes to this relation or target objects made outside of this ToMany.
487497 */
488498 public synchronized void reset () {
489499 entities = null ;
@@ -540,12 +550,14 @@ else if (delta > 0)
540550 }
541551
542552 /**
543- * Applies (persists) tracked changes (added and removed entities) to the target box
544- * and/or updates standalone relations.
545- * Note that this is done automatically when you put the source entity of this to-many relation.
546- * However, if only this to-many relation has changed, it is more efficient to call this method.
553+ * Saves changes (added and removed entities) made to this relation to the database. For some important details, see
554+ * the notes about relations of {@link Box#put(Object)}.
555+ * <p>
556+ * Note that this is called already when the object that contains this ToMany is put. However, if only this ToMany
557+ * has changed, it is more efficient to just use this method.
547558 *
548- * @throws IllegalStateException If the source entity of this to-many relation was not previously persisted
559+ * @throws IllegalStateException If the object that contains this ToMany has no ID assigned (it must have been put
560+ * before).
549561 */
550562 public void applyChangesToDb () {
551563 long id = relationInfo .sourceInfo .getIdGetter ().getId (entity );
@@ -571,7 +583,7 @@ public void applyChangesToDb() {
571583 /**
572584 * Returns true if at least one of the entities matches the given filter.
573585 * <p>
574- * For use with {@link io.objectbox.query. QueryBuilder#filter(QueryFilter)} inside a {@link QueryFilter} to check
586+ * For use with {@link QueryBuilder#filter(QueryFilter)} inside a {@link QueryFilter} to check
575587 * to-many relation entities.
576588 */
577589 @ Beta
@@ -589,7 +601,7 @@ public boolean hasA(QueryFilter<TARGET> filter) {
589601 /**
590602 * Returns true if all of the entities match the given filter. Returns false if the list is empty.
591603 * <p>
592- * For use with {@link io.objectbox.query. QueryBuilder#filter(QueryFilter)} inside a {@link QueryFilter} to check
604+ * For use with {@link QueryBuilder#filter(QueryFilter)} inside a {@link QueryFilter} to check
593605 * to-many relation entities.
594606 */
595607 @ Beta
@@ -694,6 +706,17 @@ public boolean internalCheckApplyToDbRequired() {
694706 }
695707 }
696708
709+ /**
710+ * Modifies the {@link Backlink linked} ToMany relation of added or removed target objects and schedules put by
711+ * {@link #internalApplyToDb} for them.
712+ * <p>
713+ * If {@link #setRemoveFromTargetBox} is true, removed target objects are scheduled for removal instead of just
714+ * updating their ToMany relation.
715+ * <p>
716+ * If target objects are new, schedules a put if they were added, but never if they were removed from this relation.
717+ *
718+ * @return Whether there are any target objects to put or remove.
719+ */
697720 private boolean prepareToManyBacklinkEntitiesForDb (long entityId , IdGetter <TARGET > idGetter ,
698721 @ Nullable Map <TARGET , Boolean > setAdded , @ Nullable Map <TARGET , Boolean > setRemoved ) {
699722 ToManyGetter <TARGET , Object > backlinkToManyGetter = relationInfo .backlinkToManyGetter ;
@@ -738,6 +761,9 @@ private boolean prepareToManyBacklinkEntitiesForDb(long entityId, IdGetter<TARGE
738761 }
739762 }
740763
764+ /**
765+ * Like {@link #prepareToManyBacklinkEntitiesForDb} but for the linked ToOne relation.
766+ */
741767 private boolean prepareToOneBacklinkEntitiesForDb (long entityId , IdGetter <TARGET > idGetter ,
742768 @ Nullable Map <TARGET , Boolean > setAdded , @ Nullable Map <TARGET , Boolean > setRemoved ) {
743769 ToOneGetter <TARGET , Object > backlinkToOneGetter = relationInfo .backlinkToOneGetter ;
0 commit comments