addAll/removeAll for bulk record operations,
available outside a transaction.
The standard addAll method takes a Collection<Object[]>, which forces every primitive value to be boxed
(int to Integer, double to Double, etc.). Record blocks avoid this boxing overhead by offering typed write
methods (writeInt, writeDouble, writeLong, etc.) that work directly with primitives.
Record blocks also handle automatic dictionarization of values and support BlockOptions to further optimize loading
for common patterns such as single-value or default-value columns.
Multiple threads can build and submit blocks concurrently within a single transaction, enabling parallel loading.
The next examples use a store with the following schema:
Create a block and add records
Blocks can be created and filled outside a transaction. OnlyaddRecords and removeRecords require an active
transaction. This allows you to prepare data ahead of time and keep the transaction window as short as possible.
A block has a capacity and a size. The capacity is the maximum number of records the block can hold, set when
creating the factory with createBlockFactory(tableName, capacity). The size is the number of records actually written
to the block. By default, the size equals the capacity. If you fill fewer rows than the capacity, call setSize to
indicate how many rows should be submitted.
To add records using a block:
- Get the
ITransactionManagerfrom the datastore. - Create an
ITransactionRecordBlockFactoryfor the target table, specifying a capacity and optionally providingBlockOptions. - Create an
ITransactionRecordBlockfrom the factory withcreateBlock(). - Write values using typed methods (e.g.
writeInt,writeDouble,write). - Call
setSizewith the actual number of records written. - Submit the block with
addRecordswithin a transaction.
writeDefault to write the schema default value for a column.
Block options
BlockOptions allow you to optimize blocks when some columns have predictable values.
Single-value columns
Single-value columns are bound to a fixed value shared by all rows in the block. They are immutable after block creation. This is useful when all records in a block share the same value for a column (e.g. a partition date), as it avoids redundant per-row writes.Default-value columns
Default-value columns are initialized with their default values from the table schema. Unlike single-value columns, they can be overwritten per row. This is useful when many fields have defaults and only a few rows need explicit values. A column cannot be both a single-value and a default-value column.Remove records
To remove records using a block, create a block dedicated for removal withcreateBlockForRemoval(). Only key fields
need to be written. Then submit the block with removeRecords within a transaction.
Transfer existing records
Thetransfer method copies an existing record from the most recent version of the store into a block at a given row,
looked up by key. The store must have key fields defined. This enables an update-where pattern outside a transaction:
transfer a record, modify specific fields according to existing data, and submit the block back.
transfer returns true if the record was found, false otherwise. In both cases, the key values are always written
into the block. Record blocks also provide read methods (readInt, readDouble, read, …) that return
undictionarized values, which can be used to inspect transferred data before modifying it.
Fields configured as single-value columns are not transferred, as they are already set at block creation time. For
batch transfers, transferRange transfers several records at once for better performance.
These methods do not require an active transaction.
For update-where operations inside a transaction, prefer the regular
updateWhere API.
Create blocks from a list query
ThecreateBlocksFromQuery method creates blocks populated with all records from the most recent version of a store
matching a given query’s condition. Unlike transfer which looks up individual records by key, this method works with
arbitrary conditions and does not require the store to have key fields.
The query’s selected fields determine which columns are copied into the blocks. All selected fields must be fields of
the block’s table, though they can be reached through references if the query starts from a different table.
Fields configured as single-value columns are not copied, as they are already set at block creation time.
This method benefits from the same optimizations as a regular list query. Dictionarized data is copied directly from the
store’s internal storage into the blocks, avoiding intermediate buffering.
Since the number of matching records is not known upfront and because blocks are produced in parallel for each
partition, the method creates blocks as needed and returns them as a collection. Some blocks may not be full.
This method does not require an active transaction.
Copy rows between blocks
ThecopyFrom method copies rows directly from one block to another at the dictionarized level, without
undictionarizing and re-dictionarizing each value. This is useful when generating new records from existing blocks,
for example creating risk scenarios from reference data.
Both blocks must be associated with the same table and have the same set of single-value column names.
Single-value column values are not copied: the destination block retains its own values. This method does not require
an active transaction, and does not update the destination block’s size.
The following example creates a source block, copies all its rows into a destination block, modifies the keys, and
submits both blocks: