### Start immudb with Signing Key Source: https://github.com/codenotary/immudb4j/blob/master/src/test/resources/readme.md Launches the immudb server with the specified private key to enable server-side signature signing. ```shell # Start immudb with signing. $ ./immudb --signingKey ../src/test/resources/test_private_key.pem ``` -------------------------------- ### Standard Key-Value Operations with ImmuClient in Java Source: https://context7.com/codenotary/immudb4j/llms.txt Illustrates basic key-value operations like setting, getting, and deleting data. Use these for faster operations when cryptographic verification is not required. Handles KeyNotFoundException. ```java import io.codenotary.immudb4j.ImmuClient; import io.codenotary.immudb4j.Entry; import io.codenotary.immudb4j.TxHeader; import io.codenotary.immudb4j.exceptions.KeyNotFoundException; ImmuClient client = ImmuClient.newBuilder().build(); client.openSession("defaultdb", "immudb", "immudb"); // Set a key-value pair String key = "user:1001"; byte[] value = "John Doe".getBytes(); TxHeader txHeader = client.set(key, value); System.out.println("Transaction ID: " + txHeader.getId()); // Get the value Entry entry = client.get(key); System.out.println("Value: " + new String(entry.getValue())); System.out.println("Transaction: " + entry.getTx()); System.out.println("Revision: " + entry.getRevision()); // Get value at specific transaction Entry entryAtTx = client.getAtTx(key, txHeader.getId()); // Get value at specific revision (1-based, negative for reverse) Entry entryAtRev = client.getAtRevision(key, 1); // First revision Entry prevEntry = client.getAtRevision(key, -1); // Previous revision // Handle key not found try { client.get("nonexistent-key"); } catch (KeyNotFoundException e) { System.out.println("Key does not exist"); } // Delete a key (logical deletion) client.delete(key); client.closeSession(); ``` -------------------------------- ### Standard Key-Value Get Operation Source: https://github.com/codenotary/immudb4j/blob/master/README.md Retrieve the value associated with a given key using the standard get operation. This does not involve cryptographic verification. ```java byte[] v = client.get("k123").getValue(); ``` -------------------------------- ### Perform Verified Key-Value Operations Source: https://context7.com/codenotary/immudb4j/llms.txt Executes set and get operations with cryptographic proof validation to ensure data integrity. Requires handling VerificationException to detect potential tampering. ```java import io.codenotary.immudb4j.ImmuClient; import io.codenotary.immudb4j.Entry; import io.codenotary.immudb4j.TxHeader; import io.codenotary.immudb4j.exceptions.VerificationException; ImmuClient client = ImmuClient.newBuilder().build(); client.openSession("defaultdb", "immudb", "immudb"); byte[] key = "secure-data".getBytes(); byte[] value = "sensitive information".getBytes(); try { // Verified set - commits with proof validation TxHeader txHeader = client.verifiedSet(key, value); System.out.println("Verified write at tx: " + txHeader.getId()); // Verified get - retrieves with proof validation Entry entry = client.verifiedGet(key); System.out.println("Verified value: " + new String(entry.getValue())); // Verified get at specific transaction Entry entryAtTx = client.verifiedGetAtTx(key, txHeader.getId()); // Verified get since specific transaction (for indexer sync) Entry entrySinceTx = client.verifiedGetSinceTx(key, txHeader.getId()); // Verified get at specific revision Entry entryAtRev = client.verifiedGetAtRevision(key, 1); } catch (VerificationException e) { System.err.println("Data tampering detected: " + e.getMessage()); } client.closeSession(); ``` -------------------------------- ### Stream Large Values with immuDB4j Source: https://context7.com/codenotary/immudb4j/llms.txt Efficiently handle large values using gRPC streaming for set, get, setAll, and scan operations. Configure chunk size for optimal performance. ```java import io.codenotary.immudb4j.ImmuClient; import io.codenotary.immudb4j.Entry; import io.codenotary.immudb4j.KVPair; import io.codenotary.immudb4j.TxHeader; import java.util.Arrays; import java.util.Iterator; import java.util.List; ImmuClient client = ImmuClient.newBuilder() .withChunkSize(65536) // 64 KB chunks .build(); client.openSession("defaultdb", "immudb", "immudb"); // Stream set for large values byte[] largeValue = new byte[10 * 1024 * 1024]; // 10 MB Arrays.fill(largeValue, (byte) 'X'); TxHeader txHeader = client.streamSet("large-key", largeValue); System.out.println("Streamed write at tx: " + txHeader.getId()); // Stream get for large values Entry entry = client.streamGet("large-key"); System.out.println("Retrieved " + entry.getValue().length + " bytes"); // Stream setAll for multiple large entries List largeEntries = Arrays.asList( new KVPair("large:1", new byte[1024 * 1024]), new KVPair("large:2", new byte[1024 * 1024]) ); TxHeader batchTx = client.streamSetAll(largeEntries); // Streaming scan (memory efficient for large result sets) Iterator scanIterator = client.scan("large:", false, 100); while (scanIterator.hasNext()) { Entry e = scanIterator.next(); System.out.println("Key: " + new String(e.getKey()) + ", Size: " + e.getValue().length); } client.closeSession(); ``` -------------------------------- ### Create and Configure ImmuClient in Java Source: https://context7.com/codenotary/immudb4j/llms.txt Demonstrates creating an ImmuClient with default settings or custom configurations including server URL, port, state holder, and network parameters. ```java import io.codenotary.immudb4j.ImmuClient; import io.codenotary.immudb4j.FileImmuStateHolder; // Create client with default settings (localhost:3322) ImmuClient client = ImmuClient.newBuilder().build(); // Create client with custom configuration FileImmuStateHolder stateHolder = FileImmuStateHolder.newBuilder() .withStatesFolder("./my_immuapp_states") .build(); ImmuClient customClient = ImmuClient.newBuilder() .withServerUrl("localhost") .withServerPort(3322) .withStateHolder(stateHolder) .withKeepAlivePeriod(60000) // 1 minute keep-alive .withChunkSize(65536) // 64 KB chunk size for streaming .build(); ``` -------------------------------- ### Create immudb Client with Default Configuration Source: https://github.com/codenotary/immudb4j/blob/master/README.md Instantiate an ImmuClient using default server settings. Ensure immudb is running and accessible. ```java ImmuClient immuClient = ImmuClient.newBuilder().build(); ``` -------------------------------- ### Manage Session with ImmuClient in Java Source: https://context7.com/codenotary/immudb4j/llms.txt Shows how to open, perform operations within, and close a session using the ImmuClient. Remember to shut down the client when the application exits. ```java import io.codenotary.immudb4j.ImmuClient; ImmuClient client = ImmuClient.newBuilder().build(); // Open a session with database, username, and password client.openSession("defaultdb", "immudb", "immudb"); // Perform database operations... // Close the session when done client.closeSession(); // Shutdown the client to release resources (call before process exits) client.shutdown(); ``` -------------------------------- ### Scan Keys by Prefix in Java Source: https://context7.com/codenotary/immudb4j/llms.txt Use scanAll for list-based retrieval or scan for streaming large datasets. Requires an active ImmuClient session. ```java import io.codenotary.immudb4j.ImmuClient; import io.codenotary.immudb4j.Entry; import java.util.Iterator; import java.util.List; ImmuClient client = ImmuClient.newBuilder().build(); client.openSession("defaultdb", "immudb", "immudb"); // Insert test data client.set("user:001", "Alice".getBytes()); client.set("user:002", "Bob".getBytes()); client.set("user:003", "Charlie".getBytes()); // Scan all keys with prefix List entries = client.scanAll("user:"); for (Entry entry : entries) { System.out.println(new String(entry.getKey()) + " = " + new String(entry.getValue())); } // Scan with ordering and limit List descEntries = client.scanAll("user:", true, 10); // desc=true, limit=10 // Scan with seek key (pagination) byte[] prefix = "user:".getBytes(); byte[] seekKey = "user:002".getBytes(); List pagedEntries = client.scanAll(prefix, seekKey, false, 5); // Streaming scan for large results (uses gRPC streaming) Iterator entryIterator = client.scan("user:", false, 100); while (entryIterator.hasNext()) { Entry entry = entryIterator.next(); System.out.println(new String(entry.getKey())); } client.closeSession(); ``` -------------------------------- ### Manage Key References Source: https://context7.com/codenotary/immudb4j/llms.txt Creates aliases for existing keys to avoid data duplication. Supports both standard and verified reference creation. ```java import io.codenotary.immudb4j.ImmuClient; import io.codenotary.immudb4j.Entry; import io.codenotary.immudb4j.TxHeader; import io.codenotary.immudb4j.exceptions.VerificationException; ImmuClient client = ImmuClient.newBuilder().build(); client.openSession("defaultdb", "immudb", "immudb"); // Set the original key client.set("original-key", "original-value".getBytes()); // Create a reference to the original key TxHeader txHeader = client.setReference("reference-key", "original-key"); // Getting the reference returns the original value Entry entry = client.get("reference-key"); System.out.println("Reference value: " + new String(entry.getValue())); // "original-value" // Create a reference to a specific transaction version TxHeader boundRef = client.setReference("bound-reference", "original-key", txHeader.getId()); // Verified reference creation try { TxHeader verifiedRef = client.verifiedSetReference( "verified-ref".getBytes(), "original-key".getBytes() ); } catch (VerificationException e) { System.err.println("Verification failed: " + e.getMessage()); } client.closeSession(); ``` -------------------------------- ### Manage Databases with immudb4j Source: https://context7.com/codenotary/immudb4j/llms.txt This code illustrates database management operations like creating, listing, unloading, loading, and deleting databases. Admin permissions are required for these operations. Imports for ImmuClient, Database, and List are necessary. ```java import io.codenotary.immudb4j.ImmuClient; import io.codenotary.immudb4j.Database; import java.util.List; ImmuClient client = ImmuClient.newBuilder().build(); client.openSession("defaultdb", "immudb", "immudb"); // Create a new database client.createDatabase("myapp_production"); // Create database if not exists client.createDatabase("myapp_staging", true); // List all databases List databases = client.databases(); for (Database db : databases) { System.out.println("Database: " + db.getName()); } // Unload database (frees server resources) client.unloadDatabase("myapp_staging"); // Load database (must be loaded before use) client.loadDatabase("myapp_staging"); // Delete database (must be unloaded first) client.unloadDatabase("myapp_staging"); client.deleteDatabase("myapp_staging"); client.closeSession(); ``` -------------------------------- ### Retrieve Key History in Java Source: https://context7.com/codenotary/immudb4j/llms.txt Access audit trails for keys using historyAll or streaming history. Requires handling KeyNotFoundException for non-existent keys. ```java import io.codenotary.immudb4j.ImmuClient; import io.codenotary.immudb4j.Entry; import io.codenotary.immudb4j.exceptions.KeyNotFoundException; import java.util.Iterator; import java.util.List; ImmuClient client = ImmuClient.newBuilder().build(); client.openSession("defaultdb", "immudb", "immudb"); // Create multiple versions of a key client.set("versioned-key", "version-1".getBytes()); client.set("versioned-key", "version-2".getBytes()); client.set("versioned-key", "version-3".getBytes()); // Get full history try { List history = client.historyAll("versioned-key", false, 0, 10); // Parameters: key, descending, offset, limit System.out.println("Key history:"); for (Entry entry : history) { System.out.println(" Tx " + entry.getTx() + ": " + new String(entry.getValue())); } } catch (KeyNotFoundException e) { System.out.println("Key not found"); } // Streaming history for large results Iterator historyIterator = client.history("versioned-key", true, 0, 5); // Parameters: key, descending, offset, limit while (historyIterator.hasNext()) { Entry entry = historyIterator.next(); System.out.println("Revision: " + entry.getRevision()); } client.closeSession(); ``` -------------------------------- ### Manage Users and Permissions in immuDB4j Source: https://context7.com/codenotary/immudb4j/llms.txt Create, list, activate, change passwords, grant, and revoke permissions for users. Requires SysAdmin or Admin permission level. ```java import io.codenotary.immudb4j.ImmuClient; import io.codenotary.immudb4j.user.Permission; import io.codenotary.immudb4j.user.User; import java.util.List; ImmuClient client = ImmuClient.newBuilder().build(); client.openSession("defaultdb", "immudb", "immudb"); // Create a new user with read-write permission client.createUser( "app_user", // username "SecurePass123!", // password Permission.PERMISSION_RW, // permission level "defaultdb" // database ); // List all users List users = client.listUsers(); for (User user : users) { System.out.println("User: " + user.getUser() + ", Active: " + user.isActive() + ", Created by: " + user.getCreatedBy()); } // Activate/deactivate user client.activateUser("app_user", true); // Change password (requires old password for SysAdmin) client.changePassword("app_user", "SecurePass123!", "NewSecurePass456!"); // Grant additional permission client.grantPermission("app_user", "defaultdb", Permission.PERMISSION_ADMIN); // Revoke permission client.revokePermission("app_user", "defaultdb", Permission.PERMISSION_ADMIN); // Permission levels: // - PERMISSION_SYS_ADMIN (255): System administrator // - PERMISSION_ADMIN (254): Database administrator // - PERMISSION_RW (2): Read and write // - PERMISSION_R (1): Read only // - PERMISSION_NONE (0): No permission client.closeSession(); ``` -------------------------------- ### Create immudb Client with Custom Server URL and Port Source: https://github.com/codenotary/immudb4j/blob/master/README.md Configure the ImmuClient to connect to a specific immudb server URL and port. ```java ImmuClient immuClient = ImmuClient.newBuilder() .withServerUrl("localhost") .withServerPort(3322) .build(); ``` -------------------------------- ### Manage Sorted Sets in Java Source: https://context7.com/codenotary/immudb4j/llms.txt Organize keys with scores using zAdd and retrieve them via zScanAll. Use verifiedZAdd for cryptographic proof validation. ```java import io.codenotary.immudb4j.ImmuClient; import io.codenotary.immudb4j.ZEntry; import io.codenotary.immudb4j.TxHeader; import io.codenotary.immudb4j.exceptions.VerificationException; import java.util.List; ImmuClient client = ImmuClient.newBuilder().build(); client.openSession("defaultdb", "immudb", "immudb"); // Set up keys first client.set("player:alice", "Alice Smith".getBytes()); client.set("player:bob", "Bob Jones".getBytes()); client.set("player:charlie", "Charlie Brown".getBytes()); // Add keys to sorted set with scores (leaderboard example) TxHeader tx1 = client.zAdd("leaderboard", "player:alice", 1500.0); TxHeader tx2 = client.zAdd("leaderboard", "player:bob", 2100.0); TxHeader tx3 = client.zAdd("leaderboard", "player:charlie", 1800.0); // Verified zAdd with proof validation try { TxHeader verifiedTx = client.verifiedZAdd("leaderboard", "player:alice", 1600.0); } catch (VerificationException e) { System.err.println("Verification failed: " + e.getMessage()); } // Scan sorted set (returns entries ordered by score) List leaderboard = client.zScanAll("leaderboard", false, 10); System.out.println("Leaderboard (ascending by score):"); for (ZEntry zEntry : leaderboard) { System.out.println(" " + new String(zEntry.getKey()) + " - Score: " + zEntry.getScore() + " - Value: " + new String(zEntry.getEntry().getValue())); } // Scan with score range List topPlayers = client.zScanAll( "leaderboard".getBytes(), 1700.0, // minScore 2200.0, // maxScore true, // descending 10 // limit ); client.closeSession(); ``` -------------------------------- ### Perform Atomic Multi-key Write Source: https://github.com/codenotary/immudb4j/blob/master/README.md Use `setAll` with a list of `KVPair` to ensure all entries are persisted atomically or none are. Catch `CorruptedDataException` for potential issues. ```java final List kvs = KVListBuilder.newBuilder() .add(new KVPair("sga-key1", new byte[] {1, 2})) .add(new KVPair("sga-key2", new byte[] {3, 4})) .entries(); try { immuClient.setAll(kvs); } catch (CorruptedDataException e) { // ... } ``` -------------------------------- ### Perform Atomic Multi-key Read Source: https://github.com/codenotary/immudb4j/blob/master/README.md Use `getAll` with a list of keys to retrieve entries atomically. Iterate through the `Entry` results to access keys and values. ```java List keys = Arrays.asList(key1, key2, key3); List result = immuClient.getAll(keys); for (Entry entry : result) { byte[] key = entry.getKey(); byte[] value = entry.getValue(); // ... ``` -------------------------------- ### Perform Verified Read and Write Operations Source: https://github.com/codenotary/immudb4j/blob/master/README.md Use `verifiedSet` for writing and `verifiedGet` for reading to ensure data integrity. Catch `VerificationException` to handle potential data tampering. ```java try { client.verifiedSet("k123", new byte[]{1, 2, 3}); byte[] v = client.verifiedGet("k123").getValue(); } (catch VerificationException e) { // Check if it is a data tampering detected case! } ``` -------------------------------- ### Create a New immudb Database Source: https://github.com/codenotary/immudb4j/blob/master/README.md Use the createDatabase method to provision a new database within immudb. ```java immuClient.createDatabase("db1"); ``` -------------------------------- ### Open and Close immudb User Session Source: https://github.com/codenotary/immudb4j/blob/master/README.md Initiate and terminate user sessions for interacting with immudb. Requires database name, username, and password. ```java immuClient.openSession("defaultdb", "usr1", "pwd1"); // Interact with immudb using open session. //... immuClient.closeSession(); ``` -------------------------------- ### Execute Multi-Key Batch Operations Source: https://context7.com/codenotary/immudb4j/llms.txt Performs atomic writes and reads of multiple key-value pairs in a single transaction using setAll and getAll. ```java import io.codenotary.immudb4j.ImmuClient; import io.codenotary.immudb4j.Entry; import io.codenotary.immudb4j.KVPair; import io.codenotary.immudb4j.TxHeader; import java.util.Arrays; import java.util.List; ImmuClient client = ImmuClient.newBuilder().build(); client.openSession("defaultdb", "immudb", "immudb"); // Atomic multi-key write List kvPairs = Arrays.asList( new KVPair("user:1", "Alice".getBytes()), new KVPair("user:2", "Bob".getBytes()), new KVPair("user:3", "Charlie".getBytes()) ); TxHeader txHeader = client.setAll(kvPairs); System.out.println("Batch write at tx: " + txHeader.getId()); // Atomic multi-key read List keys = Arrays.asList("user:1", "user:2", "user:3"); List entries = client.getAll(keys); for (Entry entry : entries) { System.out.println(new String(entry.getKey()) + " = " + new String(entry.getValue())); } client.closeSession(); ``` -------------------------------- ### Create immudb Client with Custom State Holder Source: https://github.com/codenotary/immudb4j/blob/master/README.md Customize the state holder for immudb4j, specifying a custom folder for storing states. ```java FileImmuStateHolder stateHolder = FileImmuStateHolder.newBuilder() .withStatesFolder("./my_immuapp_states") .build(); ImmuClient immuClient = ImmuClient.newBuilder() .withStateHolder(stateHolder) .build(); ``` -------------------------------- ### Generate ECDSA Key Pair Source: https://github.com/codenotary/immudb4j/blob/master/src/test/resources/readme.md Creates a private key and its corresponding public key using the prime256v1 curve. ```shell # Generate the public and private key pair. $ openssl ecparam -name prime256v1 -genkey -noout -out test_private_key.pem $ openssl ec -in test_private_key.pem -pubout -out test_public_key.pem ``` -------------------------------- ### Add immudb4j Gradle Dependency Source: https://github.com/codenotary/immudb4j/blob/master/README.md Include this dependency in your Gradle project to use the immudb4j client library. ```groovy compile 'io.codenotary:immudb4j:1.0.1' ``` -------------------------------- ### Manage Transactions and Indexes in immuDB4j Source: https://context7.com/codenotary/immudb4j/llms.txt Retrieve transaction data by ID, perform verified retrievals, scan transactions, and manage index flushing and compaction. ```java import io.codenotary.immudb4j.ImmuClient; import io.codenotary.immudb4j.Tx; import io.codenotary.immudb4j.TxHeader; import io.codenotary.immudb4j.exceptions.TxNotFoundException; import io.codenotary.immudb4j.exceptions.VerificationException; import java.util.List; ImmuClient client = ImmuClient.newBuilder().build(); client.openSession("defaultdb", "immudb", "immudb"); // Write some data to get transaction IDs TxHeader txHeader = client.set("tx-test", "value".getBytes()); long txId = txHeader.getId(); // Get transaction by ID try { Tx tx = client.txById(txId); TxHeader header = tx.getHeader(); System.out.println("Transaction ID: " + header.getId()); System.out.println("Entries count: " + header.getNEntries()); System.out.println("Timestamp: " + header.getTs()); } catch (TxNotFoundException e) { System.out.println("Transaction not found"); } // Verified transaction retrieval try { Tx verifiedTx = client.verifiedTxById(txId); System.out.println("Verified transaction: " + verifiedTx.getHeader().getId()); } catch (VerificationException e) { System.err.println("Verification failed: " + e.getMessage()); } // Scan transactions List transactions = client.txScanAll(1); // From tx 1 List recentTxs = client.txScanAll(txId - 5, false, 10); // Last 10 from txId-5 // Flush index (cleanup percentage 0.0-1.0) client.flushIndex(0.1f); // 10% cleanup // Full index compaction (use during low activity) client.compactIndex(); client.closeSession(); ``` -------------------------------- ### Standard Key-Value Set Operation Source: https://github.com/codenotary/immudb4j/blob/master/README.md Perform a standard set operation to store a key-value pair. This behaves like a regular key-value store without cryptographic verification. ```java client.set("k123", new byte[]{1, 2, 3}); ``` -------------------------------- ### Add immudb4j Maven Dependency Source: https://github.com/codenotary/immudb4j/blob/master/README.md Include this dependency in your Maven project to use the immudb4j client library. ```xml io.codenotary immudb4j 1.0.1 ``` -------------------------------- ### Execute SQL Transactions with immudb4j Source: https://context7.com/codenotary/immudb4j/llms.txt Use this snippet to perform SQL operations within a transaction. Ensure to call beginTransaction(), commitTransaction(), or rollbackTransaction() appropriately. Imports for ImmuClient, SQLException, SQLQueryResult, and SQLValue are required. ```java import io.codenotary.immudb4j.ImmuClient; import io.codenotary.immudb4j.sql.SQLException; import io.codenotary.immudb4j.sql.SQLQueryResult; import io.codenotary.immudb4j.sql.SQLValue; ImmuClient client = ImmuClient.newBuilder().build(); client.openSession("defaultdb", "immudb", "immudb"); try { // Begin transaction client.beginTransaction(); // Create table client.sqlExec( "CREATE TABLE IF NOT EXISTS products(" + "id INTEGER, " + "name VARCHAR[256], " + "price INTEGER, " + "active BOOLEAN, " + "PRIMARY KEY id)" ); // Insert data with positional parameters client.sqlExec( "UPSERT INTO products(id, name, price, active) VALUES (?, ?, ?, ?)", new SQLValue(1), new SQLValue("Laptop"), new SQLValue(999), new SQLValue(true) ); client.sqlExec( "UPSERT INTO products(id, name, price, active) VALUES (?, ?, ?, ?)", new SQLValue(2), new SQLValue("Mouse"), new SQLValue(29), new SQLValue(true) ); // Commit transaction client.commitTransaction(); // Query data in a new transaction client.beginTransaction(); SQLQueryResult result = client.sqlQuery( "SELECT id, name, price, active FROM products WHERE price > ?", new SQLValue(50) ); System.out.println("Products over $50:"); while (result.next()) { int id = result.getInt(0); String name = result.getString(1); int price = result.getInt(2); boolean active = result.getBoolean(3); System.out.println(" " + id + ": " + name + " - $" + price); } result.close(); client.commitTransaction(); } catch (SQLException e) { System.err.println("SQL error: " + e.getMessage()); client.rollbackTransaction(); } client.closeSession(); ``` -------------------------------- ### Check Client Connection and Server Health Source: https://context7.com/codenotary/immudb4j/llms.txt Use this snippet to verify if the immudb4j client is connected, if it has been shut down, and if the server is healthy. Ensure a session is opened before performing the health check. ```java import io.codenotary.immudb4j.ImmuClient; ImmuClient client = ImmuClient.newBuilder().build(); // Check connection status boolean connected = client.isConnected(); System.out.println("Connected: " + connected); // Check if client is shutdown boolean shutdown = client.isShutdown(); System.out.println("Shutdown: " + shutdown); // Open session for health check client.openSession("defaultdb", "immudb", "immudb"); // Server health check boolean healthy = client.healthCheck(); System.out.println("Server healthy: " + healthy); client.closeSession(); client.shutdown(); ``` -------------------------------- ### Shutdown immudb4j Client Source: https://github.com/codenotary/immudb4j/blob/master/README.md Call `shutdown` to close the connection with the immudb server. A new client instance is required after shutdown to re-establish a connection. ```java immuClient.shutdown(); ``` -------------------------------- ### Execute SQL Query Without Transaction in immudb4j Source: https://context7.com/codenotary/immudb4j/llms.txt This snippet demonstrates querying data without an active transaction, which is useful for HISTORY OF queries. Ensure necessary imports are included. ```java import io.codenotary.immudb4j.ImmuClient; import io.codenotary.immudb4j.sql.SQLException; import io.codenotary.immudb4j.sql.SQLQueryResult; import io.codenotary.immudb4j.sql.SQLValue; ImmuClient client = ImmuClient.newBuilder().build(); client.openSession("defaultdb", "immudb", "immudb"); try { // Query without transaction - useful for HISTORY OF queries SQLQueryResult result = client.sqlQueryWithoutTx( "SELECT * FROM products WHERE id = ?", new SQLValue(1) ); while (result.next()) { System.out.println("Name: " + result.getString(1)); } result.close(); } catch (SQLException e) { System.err.println("SQL error: " + e.getMessage()); } client.closeSession(); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.