Interface EntityConnection

All Superinterfaces:
AutoCloseable
All Known Subinterfaces:
HttpEntityConnection, LocalEntityConnection, RemoteEntityConnection
All Known Implementing Classes:
AbstractEntityConnection

public interface EntityConnection extends AutoCloseable
A connection to a database for querying and manipulating Entity instances.

The EntityConnection interface provides comprehensive database access with:

  • Type-safe querying with the EntityConnection.Select API
  • CRUD operations with automatic transaction management
  • Support for database functions and procedures
  • Configurable foreign key fetching depth
  • Query result caching

Transaction Management

All insert, update, and delete operations automatically commit unless run within an explicit transaction. execute(FunctionType) and execute(ProcedureType) do not perform transaction control.
 // Automatic transaction management
 Entity artist = connection.insertSelect(artistEntity);

 // Explicit transaction for multiple operations
 EntityConnection.transaction(connection, () -> {
     connection.insert(artist);
     connection.insert(album);
     connection.update(tracks);
 });

Thread Safety

Instances are safe to use from multiple threads, and typically are, since a client shares a single connection between its models. Each connection guards its statements with a private monitor, so operations from different threads never interleave. Note that this serializes rather than parallelizes: concurrent callers queue up, and a slow operation delays every other caller on the same connection. Connections do not synchronize against each other.

Two pieces of state belong to the connection rather than to the calling thread, and are therefore shared by every thread using it:

  • The transaction. One opened via startTransaction() spans all threads using the connection until it is committed or rolled back, and suspends the automatic commit their operations would otherwise perform. Do not run a transaction on a connection other threads are using.
  • The query cache, see cacheQueries().

iterator(Select) is a further exception, driving a live result set outside the monitor.

Basic Usage

 EntityConnection connection = EntityConnection.builder()
     .domain(Chinook.DOMAIN)
     .user(User.parse("scott:tiger"))
     .build();

 // Select entities
 List<Entity> albums = connection.select(Album.ARTIST_FK.equalTo(artist));

 // Insert with returned key
 Entity.Key albumKey = connection.insert(album);

 // Update modified entity
 album.set(Album.TITLE, "New Title");
 connection.update(album);

 // Delete by condition
 connection.delete(Track.ALBUM_FK.equalTo(album));
See Also:
  • Field Details

    • MAXIMUM_BATCH_SIZE

      static final PropertyValue<Integer> MAXIMUM_BATCH_SIZE
      Specifies the maximum batch operation size for insert and copy operations. This prevents memory exhaustion from excessively large batch operations.
      • Value type: Integer
      • Default value: 10,000
      • Property name: codion.db.maximumBatchSize
      • Valid range: 1-1,000,000 (typically 1,000-50,000 for most applications)
    • CONNECTION_TYPE_LOCAL

      static final String CONNECTION_TYPE_LOCAL
      Indicates a local database connection
      See Also:
    • CONNECTION_TYPE_REMOTE

      static final String CONNECTION_TYPE_REMOTE
      Indicates a remote database connection
      See Also:
    • CONNECTION_TYPE_HTTP

      static final String CONNECTION_TYPE_HTTP
      Indicates a http database connection
      See Also:
    • CLIENT_CONNECTION_TYPE

      static final PropertyValue<String> CLIENT_CONNECTION_TYPE
      Specifies whether the client should connect locally, via rmi or http, accepted values: local, remote, http
      See Also:
    • DESCRIPTION

      static final PropertyValue<String> DESCRIPTION
      Specifies a connection description, overriding the default one which usually provides a hostname or other connection based information.
      • Value type: String
      • Default value: null
      See Also:
    • VALIDITY_CHECK_INTERVAL

      static final PropertyValue<Long> VALIDITY_CHECK_INTERVAL
      Specifies the minimum time between connection validity checks, in milliseconds.

      A self-managing connection, see builder(), verifies that the underlying connection is still alive before each operation, which costs a round trip to the database or server. A connection validated within this interval is used unchecked.

      A connection dying within the interval is therefore not detected until it elapses, until then operations fail as they would on any broken connection. Specify 0 to check before every operation.

      • Value type: Long
      • Default value: 1000
  • Method Details

    • builder

      static EntityConnection.Builder<?,?> builder()

      Creates a connection builder based on system configuration, for the connection type specified by CLIENT_CONNECTION_TYPE.

      The resulting connection manages itself: it validates before each operation and re-establishes the underlying connection when it has gone bad, so it can be held on to for the lifetime of a client rather than fetched again for each operation. Contrast with LocalEntityConnection.localEntityConnection, which wraps a connection supplied by the caller and hands it back on close(), for scoped use such as a pooled connection on a server.

       // Configure connection type
       System.setProperty("codion.client.connectionType", "remote");
      
       EntityConnection connection = EntityConnection.builder()
           .domain(DomainModel.DOMAIN)
           .user(User.parse("scott:tiger"))
           .build();
      
      Returns:
      a new EntityConnection.Builder instance
      Throws:
      IllegalStateException - in case no connection is available for the configured connection type
      See Also:
    • entities

      Entities entities()
      Returns:
      the underlying domain entities
    • user

      User user()
      Returns:
      the user being used by this connection
    • clientId

      UUID clientId()
      Returns:
      the client id for this connection
    • description

      default Optional<String> description()
      Returns a description of this connection, a database or server name for example.

      Empty unless this connection manages itself, see builder(), a raw connection knowing nothing of how it was configured.

      Returns:
      a description of this connection, an empty Optional if none is available
    • clientVersion

      default Optional<Version> clientVersion()
      Returns the version of the client this connection belongs to, as reported to the server.

      Empty unless this connection manages itself, see builder().

      Returns:
      the client version, an empty Optional if none was specified
    • connected

      boolean connected()
      Returns:
      true if the connection has been established and is valid
    • close

      void close()
      Performs a rollback and disconnects this connection
      Specified by:
      close in interface AutoCloseable
    • transactionOpen

      boolean transactionOpen()
      Returns:
      true if a transaction is open, false otherwise
    • startTransaction

      void startTransaction()
      Starts a transaction on this connection.

      NOTE: A transaction should ALWAYS be used in conjunction with a try/catch block,
      in order for the transaction to be properly ended in case of an exception.
      A transaction should always be started OUTSIDE the try/catch block.

       EntityConnection connection = connection();
      
       connection.startTransaction(); // Very important, should NOT be inside the try block
       try {
           connection.insert(entity);
      
           connection.commitTransaction();
       }
       catch (DatabaseException e) {
           connection.rollbackTransaction();
           throw e;
       }
       catch (Exception e) {          // Very important to catch Exception
           connection.rollbackTransaction();
           throw new RuntimeException(e);
       }
      
      Throws:
      IllegalStateException - if a transaction is already open
      See Also:
    • rollbackTransaction

      void rollbackTransaction()
      Performs a rollback and ends the current transaction
      Throws:
      DatabaseException - in case the rollback failed
      IllegalStateException - in case a transaction is not open
      See Also:
    • commitTransaction

      void commitTransaction()
      Performs a commit and ends the current transaction
      Throws:
      DatabaseException - in case the commit failed
      IllegalStateException - in case a transaction is not open
      See Also:
    • cacheQueries

      Enables query result caching on this connection until the returned EntityConnection.QueryCache is closed.

      While active, entity select results are cached and identical selects (by EntityConnection.Select equality) return the cached result. Intended for short-lived, read-only scopes, such as application or model initialization, where the same lookup entities would otherwise be selected repeatedly:

       try (QueryCache cache = connection.cacheQueries()) {
         // initialize application models
       }
      

      Contract:

      • Cached results are shared instances, the same List is returned for every cache hit. The list is unmodifiable and its entities are immutable, along with their foreign key references, so that no caller can modify what the next one receives. Use Entity.copy().mutable() to obtain a modifiable copy.
      • The cache is not invalidated by inserts, updates, deletes or transaction rollback on this connection, a select performed inside a transaction and cached may represent uncommitted or rolled-back data.
      • EntityConnection.Select.forUpdate() selects always bypass the cache and return mutable entities.
      • Scopes do not nest, calling this method while a cache is active throws IllegalStateException.
      Returns:
      a new active EntityConnection.QueryCache
      Throws:
      IllegalStateException - in case a query cache is already active
    • execute

      <C extends EntityConnection, P, R> @Nullable R execute(FunctionType<C,P,R> functionType)
      Executes the function with the given type with no parameter
      Type Parameters:
      C - the connection type
      P - the parameter type
      R - the return value type
      Parameters:
      functionType - the function type
      Returns:
      the function return value
      Throws:
      DatabaseException - in case anything goes wrong during the execution
    • execute

      <C extends EntityConnection, P, R> @Nullable R execute(FunctionType<C,P,R> functionType, @Nullable P parameter)
      Executes the function with the given type
      Type Parameters:
      C - the connection type
      P - the parameter type
      R - the return value type
      Parameters:
      functionType - the function type
      parameter - the function parameter
      Returns:
      the function return value
      Throws:
      DatabaseException - in case anything goes wrong during the execution
    • execute

      <C extends EntityConnection, P> void execute(ProcedureType<C,P> procedureType)
      Executes the procedure with the given type with no parameter
      Type Parameters:
      C - the connection type
      P - the procedure parameter type
      Parameters:
      procedureType - the procedure type
      Throws:
      DatabaseException - in case anything goes wrong during the execution
    • execute

      <C extends EntityConnection, P> void execute(ProcedureType<C,P> procedureType, @Nullable P parameter)
      Executes the procedure with the given type
      Type Parameters:
      C - the connection type
      P - the parameter type
      Parameters:
      procedureType - the procedure type
      parameter - the procedure parameter
      Throws:
      DatabaseException - in case anything goes wrong during the execution
    • insert

      Entity.Key insert(Entity entity)
      Inserts the given entity, returning the primary key. Performs a commit unless a transaction is open.
       Entities entities = connection.entities();
      
       Entity artist = entities.entity(Artist.TYPE)
           .with(Artist.NAME, "The Beatles")
           .build();
      
       Entity.Key artistKey = connection.insert(artist);
      
      Parameters:
      entity - the entity to insert
      Returns:
      the primary key of the inserted entity
      Throws:
      DatabaseException - in case of a database exception
    • insertSelect

      Entity insertSelect(Entity entity)
      Inserts the given entity, returning the inserted entity. Performs a commit unless a transaction is open.

      The returned entity includes any lazy-loaded attributes (defined with ColumnDefinition.Builder.selected(boolean)) that were contained in the entity being inserted.

       Entity album = entities.entity(Album.TYPE)
           .with(Album.ARTIST_FK, artist)
           .with(Album.TITLE, "Abbey Road")
           .build();
      
       // Insert and get the entity with generated ID
       album = connection.insertSelect(album);
       Long generatedId = album.get(Album.ID);
      
      Parameters:
      entity - the entity to insert
      Returns:
      the inserted entity
      Throws:
      DatabaseException - in case of a database exception
      InsertEntityException - in case of no insertable values or if there is a mismatch between expected and actual number of inserted rows
    • insert

      Collection<Entity.Key> insert(Collection<Entity> entities)
      Inserts the given entities, returning the primary keys in the same order as they were received. Performs a commit unless a transaction is open.
      Parameters:
      entities - the entities to insert
      Returns:
      the primary keys of the inserted entities, in the same order as they were received
      Throws:
      DatabaseException - in case of a database exception
    • insertSelect

      Collection<Entity> insertSelect(Collection<Entity> entities)
      Inserts the given entities, returning the inserted entities. Performs a commit unless a transaction is open.

      The returned entities include any lazy-loaded attributes (defined with ColumnDefinition.Builder.selected(boolean)) that were contained in the entities being inserted.

      Note: When inserting multiple entities, if a lazy attribute is contained in any of the entities, it will be included in the select for all of them. This means that if one entity has a lazy attribute with a value, that attribute will be loaded for all entities in the batch, even those where it wasn't contained.

      Parameters:
      entities - the entities to insert
      Returns:
      the inserted entities, in no particular order
      Throws:
      DatabaseException - in case of a database exception
      InsertEntityException - in case of no insertable values or if there is a mismatch between expected and actual number of inserted rows
    • update

      void update(Entity entity)
      Updates the given entity based on its attribute values. Throws an exception if the given entity is unmodified. Performs a commit unless a transaction is open.
      Parameters:
      entity - the entity to update
      Throws:
      DatabaseException - in case of a database exception
      UpdateEntityException - in case of an unmodified entity or if there is a mismatch between expected and actual number of updated rows
      EntityModifiedException - in case the entity has been modified or deleted by another user
    • updateSelect

      Entity updateSelect(Entity entity)
      Updates the given entity based on its attribute values. Returns the updated entity. Throws an exception if the given entity is unmodified. Performs a commit unless a transaction is open.

      The returned entity includes any lazy-loaded attributes (defined with ColumnDefinition.Builder.selected(boolean)) that were contained in the entity being updated, preventing lazy-loaded values from being lost during updates.

      Parameters:
      entity - the entity to update
      Returns:
      the updated entity
      Throws:
      DatabaseException - in case of a database exception
      UpdateEntityException - in case of an unmodified entity or if there is a mismatch between expected and actual number of updated rows
      EntityModifiedException - in case the entity has been modified or deleted by another user
    • update

      void update(Collection<Entity> entities)
      Updates the given entities based on their attribute values. Throws an exception if any of the given entities is unmodified. Performs a commit unless a transaction is open.
      Parameters:
      entities - the entities to update
      Throws:
      DatabaseException - in case of a database exception
      UpdateEntityException - in case of an unmodified entity or if there is a mismatch between expected and actual number of updated rows
      EntityModifiedException - in case an entity has been modified or deleted by another user
    • updateSelect

      Collection<Entity> updateSelect(Collection<Entity> entities)
      Updates the given entities based on their attribute values. Returns the updated entities, in no particular order. Throws an exception if any of the given entities is unmodified. Performs a commit unless a transaction is open.

      The returned entities include any lazy-loaded attributes (defined with ColumnDefinition.Builder.selected(boolean)) that were contained in the entities being updated, preventing lazy-loaded values from being lost during updates.

      Note: When updating multiple entities, if a lazy attribute is contained in any of the entities, it will be included in the select for all of them. This means that if one entity has a lazy attribute loaded, that attribute will be loaded for all entities in the batch, even those where it wasn't originally loaded.

      Parameters:
      entities - the entities to update
      Returns:
      the updated entities, in no particular order
      Throws:
      DatabaseException - in case of a database exception
      UpdateEntityException - in case of an unmodified entity or if there is a mismatch between expected and actual number of updated rows
      EntityModifiedException - in case an entity has been modified or deleted by another user
    • update

      int update(EntityConnection.Update update)
      Performs an update based on the given update, updating the columns found in the EntityConnection.Update.values() map, using the associated value.
       // Update all customers without email
       int updatedCount = connection.update(
           Update.where(Customer.EMAIL.isNull())
               .set(Customer.EMAIL, "noemail@example.com")
               .set(Customer.SUPPORTREP_ID, supportRepId));
      
       // Bulk price increase
       int tracksUpdated = connection.update(
           Update.where(Track.GENRE_FK.equalTo(genre))
               .set(Track.UNITPRICE, newPrice));
      
      Parameters:
      update - the update to perform
      Returns:
      the number of affected rows
      Throws:
      DatabaseException - in case of a database exception
    • update

      default int update(Supplier<EntityConnection.Update> update)
      Convenience overload accepting an EntityConnection.Update.Builder or any Supplier of EntityConnection.Update, removing the need for a trailing EntityConnection.Update.Builder.build() call.
      Parameters:
      update - the update supplier, typically an EntityConnection.Update.Builder
      Returns:
      the number of affected rows
      Throws:
      DatabaseException - in case of a database exception
      See Also:
    • delete

      void delete(Entity.Key key)
      Deletes the entity with the given primary key. Performs a commit unless a transaction is open.
      Parameters:
      key - the primary key of the entity to delete
      Throws:
      DatabaseException - in case of a database exception
      DeleteEntityException - in case no row or multiple rows were deleted
    • delete

      void delete(Collection<Entity.Key> keys)
      Deletes the entities with the given primary keys. This method respects the iteration order of the given collection by first deleting all entities of the first entityType encountered, then all entities of the next entityType encountered and so on. This allows the deletion of multiple entities forming a master detail hierarchy, by having the detail entities appear before their master entities in the collection. Performs a commit unless a transaction is open.
      Parameters:
      keys - the primary keys of the entities to delete
      Throws:
      DatabaseException - in case of a database exception
      DeleteEntityException - in case the number of deleted rows does not match the number of keys
    • delete

      int delete(Condition condition)
      Deletes the entities specified by the given condition. Performs a commit unless a transaction is open.
      Parameters:
      condition - the condition specifying the entities to delete
      Returns:
      the number of deleted rows
      Throws:
      DatabaseException - in case of a database exception
    • select

      <T> List<T> select(Column<T> column)
      Selects ordered and distinct non-null values of the given column.
      Type Parameters:
      T - the value type
      Parameters:
      column - column
      Returns:
      the values of the given column
      Throws:
      DatabaseException - in case of a database exception
      IllegalArgumentException - in case the given column is not associated with a table column
      UnsupportedOperationException - in case the entity uses a custom column clause or if the column represents an aggregate value
    • select

      <T> List<T> select(Column<T> column, Condition condition)
      Selects distinct non-null values of the given column. The result is ordered by the selected column.
      Type Parameters:
      T - the value type
      Parameters:
      column - column
      condition - the condition
      Returns:
      the values of the given column
      Throws:
      DatabaseException - in case of a database exception
      IllegalArgumentException - in case the given column is not associated with a table column
      UnsupportedOperationException - in case the entity uses a custom column clause or if the column represents an aggregate value
    • select

      <T> List<T> select(Column<T> column, EntityConnection.Select select)
      Selects distinct non-null values of the given column. If the select provides no order by clause the result is ordered by the selected column.
      Type Parameters:
      T - the value type
      Parameters:
      column - column
      select - the select to perform
      Returns:
      the values of the given column
      Throws:
      DatabaseException - in case of a database exception
      IllegalArgumentException - in case the column and select condition entity types don't match
      UnsupportedOperationException - in case the entity uses a custom column clause or if the column represents an aggregate value
    • select

      default <T> List<T> select(Column<T> column, Supplier<EntityConnection.Select> select)
      Convenience overload accepting a EntityConnection.Select.Builder or any Supplier of EntityConnection.Select, removing the need for a trailing EntityConnection.Select.Builder.build() call.
      Type Parameters:
      T - the column value type
      Parameters:
      column - the column for which to retrieve the values
      select - the select supplier, typically a EntityConnection.Select.Builder
      Returns:
      the values of the given column
      Throws:
      DatabaseException - in case of a database exception
      See Also:
    • select

      Entity select(Entity.Key key)
      Selects an entity by key
      Parameters:
      key - the key of the entity to select
      Returns:
      an entity having the key key
      Throws:
      DatabaseException - in case of a database exception
      EntityNotFoundException - in case the entity was not found
      MultipleEntitiesFoundException - in case multiple entities were found
    • selectSingle

      Entity selectSingle(Condition condition)
      Selects a single entity based on the specified condition
      Parameters:
      condition - the condition specifying the entity to select
      Returns:
      the entity based on the given condition
      Throws:
      DatabaseException - in case of a database exception
      EntityNotFoundException - in case the entity was not found
      MultipleEntitiesFoundException - in case multiple entities were found
    • selectSingle

      Entity selectSingle(EntityConnection.Select select)
      Selects a single entity based on the specified select
      Parameters:
      select - the select to perform
      Returns:
      the entity based on the given select
      Throws:
      DatabaseException - in case of a database exception
      EntityNotFoundException - in case the entity was not found
      MultipleEntitiesFoundException - in case multiple entities were found
    • selectSingle

      default Entity selectSingle(Supplier<EntityConnection.Select> select)
      Convenience overload accepting a EntityConnection.Select.Builder or any Supplier of EntityConnection.Select, removing the need for a trailing EntityConnection.Select.Builder.build() call.
      Parameters:
      select - the select supplier, typically a EntityConnection.Select.Builder
      Returns:
      the entity based on the given select
      Throws:
      DatabaseException - in case of a database exception
      EntityNotFoundException - in case the entity was not found
      MultipleEntitiesFoundException - in case multiple entities were found
      See Also:
    • select

      Selects entities based on the given keys
      Parameters:
      keys - the keys used in the condition
      Returns:
      entities based on keys
      Throws:
      DatabaseException - in case of a database exception
    • select

      List<Entity> select(Condition condition)
      Selects entities based on the given condition
       // Select all jazz albums
       Entity jazz = connection.selectSingle(Genre.NAME.equalTo("Jazz"));
       List<Entity> jazzTracks = connection.select(Track.GENRE_FK.equalTo(jazz));
      
       // Select with composite condition
       List<Entity> longExpensiveTracks = connection.select(and(
           Track.UNITPRICE.greaterThan(0.99),
           Track.MILLISECONDS.greaterThan(300_000)));
      
      Parameters:
      condition - the condition specifying which entities to select
      Returns:
      entities based on the given condition
      Throws:
      DatabaseException - in case of a database exception
    • select

      Selects entities based on the given select
       // Select with ordering and limit
       List<Entity> recentInvoices = connection.select(
           Select.where(Invoice.CUSTOMER_FK.equalTo(customer))
               .orderBy(OrderBy.descending(Invoice.DATE))
               .limit(10));
      
       // Select specific attributes only
       List<Entity> trackInfo = connection.select(
           Select.where(Track.ALBUM_FK.equalTo(album))
               .attributes(Track.NAME, Track.MILLISECONDS));
      
       // Control foreign key fetching depth
       List<Entity> tracks = connection.select(
           Select.where(Track.GENRE_FK.equalTo(genre))
               .referenceDepth(0));  // Don't fetch foreign keys
      
      Parameters:
      select - the select to perform
      Returns:
      entities based on the given select
      Throws:
      DatabaseException - in case of a database exception
    • select

      default List<Entity> select(Supplier<EntityConnection.Select> select)
      Convenience overload accepting a EntityConnection.Select.Builder or any Supplier of EntityConnection.Select, removing the need for a trailing EntityConnection.Select.Builder.build() call.
      Parameters:
      select - the select supplier, typically a EntityConnection.Select.Builder
      Returns:
      entities based on the given select
      Throws:
      DatabaseException - in case of a database exception
      See Also:
    • dependencies

      Map<EntityType,Collection<Entity>> dependencies(Collection<Entity> entities)
      Selects the entities that depend on the given entities via (non-soft) foreign keys, mapped to corresponding entityTypes
      Parameters:
      entities - the entities for which to retrieve dependencies, must be of same type
      Returns:
      the entities that depend on entities
      Throws:
      IllegalArgumentException - in case the entities are not of the same type
      DatabaseException - in case of a database exception
      See Also:
    • count

      int count(EntityConnection.Count count)
      Counts the number of rows returned based on the given count conditions
      Parameters:
      count - the count conditions
      Returns:
      the number of rows fitting the given count conditions
      Throws:
      DatabaseException - in case of a database exception
    • count

      default int count(Supplier<EntityConnection.Count> count)
      Convenience overload accepting a EntityConnection.Count.Builder or any Supplier of EntityConnection.Count, removing the need for a trailing EntityConnection.Count.Builder.build() call.
      Parameters:
      count - the count supplier, typically a EntityConnection.Count.Builder
      Returns:
      the number of rows fitting the given count conditions
      Throws:
      DatabaseException - in case of a database exception
      See Also:
    • report

      <P, R> R report(ReportType<P,R> reportType, @Nullable P parameter)
      Takes a ReportType object using a JDBC datasource and returns an initialized report result object
      Type Parameters:
      P - the report parameters type
      R - the report result type
      Parameters:
      reportType - the report to fill
      parameter - the report parameter, if any
      Returns:
      the filled result object
      Throws:
      DatabaseException - in case of a database exception
      ReportException - in case of a report exception
      See Also:
    • iterator

      EntityResultIterator iterator(Condition condition)
      Returns a result set iterator based on the given query condition.

      Remote Connection Performance: When using remote connections, each call to Iterator.hasNext() and Iterator.next() involves a network round-trip. For large result sets, consider using select(Condition) instead to load entities in a single batch.

      Remote Connection Resource Management: Iterators over remote connections that remain idle for longer than the configured timeout (codion.db.remote.iteratorTimeout, default 5 minutes) are automatically closed server-side.

      Local Connection Sharing: A local iterator drives a live result set outside the connection monitor, so do not perform other operations on the same connection while iterating, and on databases whose cursors do not survive a commit (such as PostgreSQL) wrap the iteration in a transaction to keep the cursor open.

      Always use try-with-resources to ensure proper cleanup:

       try (EntityResultIterator iterator = connection.iterator(condition)) {
         while (iterator.hasNext()) {
           Entity entity = iterator.next();
           // process entity
         }
       }
      
      Parameters:
      condition - the query condition
      Returns:
      an iterator for the given query condition
      Throws:
      DatabaseException - in case of a database exception, or in case of a communication exception with remote connections
      UnsupportedOperationException - in case of an HTTP connection, which does not support iteration
      See Also:
    • iterator

      Returns a result set iterator based on the given select.

      Remote Connection Performance: When using remote connections, each call to Iterator.hasNext() and Iterator.next() involves a network round-trip. For large result sets, consider using select(Select) instead to load entities in a single batch.

      Remote Connection Resource Management: Iterators over remote connections that remain idle for longer than the configured timeout (codion.db.remote.iteratorTimeout, default 5 minutes) are automatically closed server-side.

      Local Connection Sharing: A local iterator drives a live result set outside the connection monitor, so do not perform other operations on the same connection while iterating, and on databases whose cursors do not survive a commit (such as PostgreSQL) wrap the iteration in a transaction to keep the cursor open.

      Always use try-with-resources to ensure proper cleanup:

       try (EntityResultIterator iterator = connection.iterator(select)) {
         while (iterator.hasNext()) {
           Entity entity = iterator.next();
           // process entity
         }
       }
      
      Parameters:
      select - the query select
      Returns:
      an iterator for the given query select
      Throws:
      DatabaseException - in case of a database exception, or in case of a communication exception with remote connections
      UnsupportedOperationException - in case of an HTTP connection, which does not support iteration
      See Also:
    • iterator

      Convenience overload accepting a EntityConnection.Select.Builder or any Supplier of EntityConnection.Select, removing the need for a trailing EntityConnection.Select.Builder.build() call.
      Parameters:
      select - the select supplier, typically a EntityConnection.Select.Builder
      Returns:
      an iterator for the given query select
      Throws:
      DatabaseException - in case of a database exception, or in case of a communication exception with remote connections
      See Also:
    • transaction

      static void transaction(EntityConnection connection, EntityConnection.Transactional transactional)
      Executes the given EntityConnection.Transactional instance within a transaction on the given connection, committing on success and rolling back on exception. Any DatabaseExceptions, RuntimeExceptions or Errors encountered are rethrown, other exceptions are rethrown wrapped in a RuntimeException.

      If a transaction is already open on the connection, the code is executed within the existing transaction without starting a new one. The outermost caller controls the transaction boundary (commit/rollback). This allows nested calls without requiring explicit transaction state checks.

       EntityConnection connection = connection();
       transaction(connection, () -> {
       	 // Delete the playlist tracks
         connection.delete(PlaylistTrack.PLAYLIST_FK.in(playlists));
       	 // Then delete the playlists
         connection.delete(primaryKeys(playlists));
       });
      
      Parameters:
      connection - the connection to use
      transactional - the transactional to run
      Throws:
      DatabaseException - in case of a database exception
      RuntimeException - in case of exceptions other than DatabaseException
    • transaction

      static <T> @Nullable T transaction(EntityConnection connection, EntityConnection.TransactionalResult<T> transactional)
      Executes the given EntityConnection.TransactionalResult instance within a transaction on the given connection, committing on success and rolling back on exception. Any DatabaseExceptions, RuntimeExceptions or Errors encountered are rethrown, other exceptions are rethrown wrapped in a RuntimeException.

      If a transaction is already open on the connection, the code is executed within the existing transaction without starting a new one. The outermost caller controls the transaction boundary (commit/rollback). This allows nested calls without requiring explicit transaction state checks.

       EntityConnection connection = connection();
       Entity randomPlaylist = transaction(connection, () ->
         connection.execute(Playlist.RANDOM_PLAYLIST, parameters));
      
      Type Parameters:
      T - the result type
      Parameters:
      connection - the connection to use
      transactional - the transactional to run
      Returns:
      the result
      Throws:
      DatabaseException - in case of a database exception
      RuntimeException - in case of exceptions other than DatabaseException
    • batchCopy

      static EntityConnection.BatchCopy.Builder batchCopy(EntityConnection source, EntityConnection destination)
      Creates a new EntityConnection.BatchCopy.Builder instance for copying entities from source to destination, with a default batch size of 100. Performs a commit after each batchSize number of inserts, unless the destination connection has an open transaction. Call EntityConnection.BatchCopy.Builder.execute() to perform the copy operation.
      Parameters:
      source - the source connection
      destination - the destination connection
      Returns:
      a new EntityConnection.BatchCopy.Builder instance
    • batchInsert

      static EntityConnection.BatchInsert.Builder batchInsert(EntityConnection connection, Iterator<Entity> entities)
      Creates a new EntityConnection.BatchInsert.Builder instance based on the given iterator, with a default batch size of 100. Performs a commit after each batchSize number of inserts, unless the destination connection has an open transaction. Call EntityConnection.BatchInsert.Builder.execute() to perform the insert operation.
      Parameters:
      connection - the entity connection to use when inserting
      entities - the entities to insert
      Returns:
      a new EntityConnection.BatchInsert.Builder instance