LangChain Java Integration

Use LangChain4j with Oracle AI Database to store embeddings and run vector search from Java applications.

LangChain4j provides OracleEmbeddingStore, an embedding store that integrates with Oracle Database AI Vector Search. Use it to persist text segments, embeddings, and metadata in Oracle AI Database.

Contents

Add the Maven Dependency

Add the LangChain4j Oracle module to your Maven build.

<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-oracle</artifactId>
    <version>1.16.2-beta26</version>
</dependency>

Use the version that matches the rest of your LangChain4j dependencies.

Configure a Data Source

OracleEmbeddingStore requires a Java DataSource and an embedding table configuration. Use a pooled data source, such as Oracle Universal Connection Pool or HikariCP, for production applications.

DataSource dataSource = myDataSource;

Connection pooling avoids the latency of opening a new database connection for each embedding store operation.

Use an Existing Embedding Table

If the embedding table already exists, pass the table name to the builder.

EmbeddingStore<TextSegment> embeddingStore = OracleEmbeddingStore.builder()
    .dataSource(dataSource)
    .embeddingTable("my_embedding_table")
    .build();

By default, LangChain4j expects the embedding table to use the following columns.

Column Type Description
id VARCHAR(36) Primary key that stores generated UUID strings.
embedding VECTOR(*, FLOAT32) Embedding vector.
text CLOB Text segment content.
metadata JSON Text segment metadata.

Create an Embedding Table

If the table does not exist, pass a create option to the embedding table configuration.

EmbeddingStore<TextSegment> embeddingStore = OracleEmbeddingStore.builder()
    .dataSource(dataSource)
    .embeddingTable("my_embedding_table", CreateOption.CREATE_IF_NOT_EXISTS)
    .build();

Use CREATE_IF_NOT_EXISTS for application startup flows that should create the table only when it is missing.

Caution: Use replacement create options only in development or controlled rebuild workflows because they can remove existing embedding data.

Customize Table Columns

Use EmbeddingTable.builder() when your table uses custom names for the table or columns.

OracleEmbeddingStore embeddingStore = OracleEmbeddingStore.builder()
    .dataSource(dataSource)
    .embeddingTable(
        EmbeddingTable.builder()
            .createOption(CreateOption.CREATE_OR_REPLACE)
            .name("my_embedding_table")
            .idColumn("id_column_name")
            .embeddingColumn("embedding_column_name")
            .textColumn("text_column_name")
            .metadataColumn("metadata_column_name")
            .build()
    )
    .build();

Use CreateOption.NONE when the table already exists and you want LangChain4j to use it without creating or replacing it.

Create an IVF Vector Index

Use an IVF index on the embedding column when approximate vector search is appropriate for your workload.

OracleEmbeddingStore embeddingStore = OracleEmbeddingStore.builder()
    .dataSource(dataSource)
    .embeddingTable(
        EmbeddingTable.builder()
            .createOption(CreateOption.CREATE_OR_REPLACE)
            .name("my_embedding_table")
            .idColumn("id_column_name")
            .embeddingColumn("embedding_column_name")
            .textColumn("text_column_name")
            .metadataColumn("metadata_column_name")
            .build()
    )
    .index(
        Index.ivfIndexBuilder()
            .createOption(CreateOption.CREATE_OR_REPLACE)
            .build()
    )
    .build();

IVF, or Inverted File Flat, indexes can improve vector search performance for large embedding tables.

Create a JSON Metadata Index

Use a JSON metadata index when retrieval filters target specific metadata keys.

OracleEmbeddingStore embeddingStore = OracleEmbeddingStore.builder()
    .dataSource(dataSource)
    .embeddingTable(
        EmbeddingTable.builder()
            .createOption(CreateOption.CREATE_OR_REPLACE)
            .name("my_embedding_table")
            .idColumn("id_column_name")
            .embeddingColumn("embedding_column_name")
            .textColumn("text_column_name")
            .metadataColumn("metadata_column_name")
            .build()
    )
    .index(
        Index.jsonIndexBuilder()
            .createOption(CreateOption.CREATE_OR_REPLACE)
            .key("name", String.class, JSONIndexBuilder.Order.ASC)
            .key("year", Integer.class, JSONIndexBuilder.Order.DESC)
            .build()
    )
    .build();

The JSON index is a function-based index over selected keys in the metadata column.

Use the Embedding Store in Retrieval Workflows

Use OracleEmbeddingStore anywhere LangChain4j expects an EmbeddingStore<TextSegment>. A typical retrieval workflow follows this sequence:

  1. Create or configure a pooled DataSource.
  2. Build an OracleEmbeddingStore.
  3. Generate embeddings with a LangChain4j embedding model.
  4. Add text segments, embeddings, and metadata to the store.
  5. Query the store by vector similarity.
  6. Pass retrieved text segments to a chat model as grounding context.

The Oracle embedding store uses cosine similarity to calculate the distance between vectors.

Review Reference Links