# Miscellaneous Java Details

> ## Free Memory Threshold

> An update operation on a transient database can run out of memory in the middle of a transaction, and in this case it is quite possible that the transaction won’t be able to be rolled back. To address this, the `McoSqlEngine::setFreeMemoryThreshold()` method is used in the C++ API. However, in the Java API this memory limit is managed by setting the Database::Parameter `sqlWorkspaceLimit` passed to the `Database::open()` call. For example:

>         parameters.sqlWorkspaceLimit = 2 * 1024*1024;
>         ...
>         db.open("quotadb", parameters, devs);

> (Note that the default value for `sqlWorkspaceLimit` is 0 which means unlimited memory.)

> ## Java Garbage Collection

> The Java garbage collector does not always release objects in time for other database operations to execute which can cause unnecessary memory consumption. To avoid memory consumption it is recommended to add a call to the `SqlResultSet` `close()` method to explicitly release resources occupied by a result set as soon after a query as practical.

> Generally it is recommended to explicitly call `SqlResultSet` methods `close()` and `release()` in any long processing loop because the Java garbage collector may hold objects unreleased in order to improve performance.

> ## Managing Transactions

> Whereas the C++ API uses `implicit` transactions by default, where each call of `executeStatement()` or `executeQuery()` internally performs a transaction `start` and `commit`, Java applications need to perform `explicit` transaction blocking. This is done by explicitly starting and committing (or rolling back) the transaction as demonstrated in the code snippet below:

>         SqlLocalConnection con = db.connectSql();
>         con.startTransaction(Database.TransactionType.ReadWrite);
>         con.executeStatement("insert into MyTable (pk,value) values (?,?)", 2012, "Good bye");
>         con.executeStatement("insert into MyTable (pk,value) values (?,?)", 2013, "Hello");
>         con.commitTransaction();

> (Note also that you can use the `Connection::checkpointTransaction()` method to update indexes and make objects visible to queries while the transaction is still open.)

> ## Using the Java SqlAggregator

> The `SqlAggregator` class acts like a distributed connection, but within a single process. In order to use the `SqlAggregator` the Java application creates an array of `SqlLocalConnection` objects to run as shards. Then it starts all of the `SqlLocalConnection` objects and passes the array to the `SqlAggregator` constructor. For example:

>         SqlLocalConnection [] shards = new SqlLocalConnection[NSHARDS];
>         for (int i = 0; i < NSHARDS; i++)
>         {
>             shards[i] = create_database("aggg" + Integer.toString(i), config, is_dptr);
>         }
>         SqlAggregator agg = new SqlAggregator(shards, 64*1024);

> Once the aggregator has been created and initialized it can be used exactly as the `SqlLocalConnection`. For example to perform queries:

>          agg.executeStatement("1:insert into MyTable (pk,value) values (?,?)", 2012, "Good bye"));

> When no longer required, the aggregator must be closed through the `SqlAgregator.disconnect()` method, and after that close the `SqlLocalConnection` objects:

>         agg.disconnect();
>         for (int i = 0; i < NSHARDS; i++)
>         {
>             shards[i].disconnect();
>         }

> ## SQL String Length

> Whereas for the `executeStatement()` and the `executeQuery()` methods of the SqlLocalConnection class, there is no limit to the length of the statement string argument, for the SqlRemoteConnection class the statement string length is limited by the `bufferSize` argument passed to the constructor. The default value is 64 Kb. (This applies as well to the SqlAggregator class). Please refer to the SQL Statement Strings page for further details.