Building AI-Powered Database Apps with Hibernate Vector and the Oracle Database 23ai — Part 2 — Using the Hibernate Vector module with Oracle AI Vector Search

Juarez Junior
7 min readMar 10, 2025

--

Oracle Database 23ai

by Juarez Junior

Introduction — Hibernate Vector module with Oracle AI Vector Search

Part 1 in this series introduced the Hibernate Vector module and how to use it with Oracle Database 23ai by creating Hibernate DB apps that work with vectors and tables with embeddings of the VECTOR data type. Please check it if you need a quick introduction to the topic.

Now Part 2 will show you how to implement similarity search using the Hibernate Vector module, Jakarta Persistence, Oracle AI Vector Search, Oracle JDBC, and the Oracle Database 23ai.

The good news is that you can still use HQL (Hibernate Query Language) combined with several functions as the Hibernate Vector module implementation maps to the underlying functions implemented by Oracle AI Vector Search.

So, without further ado, let’s get started!

Prerequisites

Step 1: Configure Your Java Project

There are no changes here - the steps are pretty much the same as in Part 1 of this series. This assumes you know Java, Hibernate, Maven or Gradle, and relational database concepts. Start by creating a Maven project (or using your preferred build tool). Add the dependencies to your build configuration file.

Using Maven

<dependencies>
<!-- Oracle JDBC Driver -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc17</artifactId>
<version>23.7.0.25.01</version>
</dependency>
<!-- Oracle UCP -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ucp17</artifactId>
<version>23.7.0.25.01</version>
</dependency>
<!-- Hibernate Core -->
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.6.10.Final</version>
</dependency>
<!-- Hibernate Vector Module -->
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-vector</artifactId>
<version>6.6.10.Final</version>
</dependency>
<!-- Jakarta EE -->
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>jakarta.transaction</groupId>
<artifactId>jakarta.transaction-api</artifactId>
<version>2.0.1</version>
</dependency>

Using Gradle

dependencies {
// Oracle JDBC Driver
implementation 'com.oracle.database.jdbc:ojdbc17:23.7.0.25.01'

// Oracle UCP
implementation 'com.oracle.database.jdbc:ucp17:23.7.0.25.01'

// Hibernate Core
implementation 'org.hibernate.orm:hibernate-core:6.6.10.Final'

// Hibernate Vector Module
implementation 'org.hibernate.orm:hibernate-vector:6.6.10.Final'

// Jakarta EE
implementation 'jakarta.persistence:jakarta.persistence-api:3.2.0'
implementation 'jakarta.transaction:jakarta.transaction-api:2.0.1'
}

Step 2: Configure Hibernate

The same here - no changes at all. As usual, you must create your Hibernate configuration file (hibernate.properties or hibernate.cfg.xml) to enable it to access your Oracle Database 23ai instance.

# Oracle JDBC driver
hibernate.connection.url=jdbc:oracle:thin:@<DB_HOST>:<DB_PORT>/FREEPDB1
hibernate.connection.username=<DB_USER>
hibernate.connection.password=<DB_PASSWORD>
hibernate.connection.driver_class=oracle.jdbc.OracleDriver
hibernate.dialect=org.hibernate.dialect.OracleDialect
hibernate.show_sql=false
hibernate.hbm2ddl.auto=update

# Oracle Universal Connection Pool (UCP)
hibenrate.connection.driver_class=oracle.jdbc.OracleDriver
hibernate.oracleucp.connectionFactoryClassName=oracle.jdbc.datasource.impl.OracleDataSource
hibernate.oracleucp.initialPoolSize=3
hibernate.oracleucp.minPoolSize=3
hibernate.oracleucp.maxPoolSize=5
hibernate.oracleucp.connectionPoolName=hibernateVectorPool
hibernate.oracleucp.dataSourceName=hibernateVectorDataSource
hibernate.oracleucp.connectionProperties={autoCommit=false}
hibernate.oracleucp.fastConnectionFailoverEnabled=false
hibernate.oracleucp.validateConnectionOnBorrow=true
hibernate.oracleucp.secondsToTrustIdleConnection=120
hibernate.oracleucp.inactiveConnectionTimeout=180
hibernate.oracleucp.maxStatements=20

Step 3: Create Java Entity With Vector Data Type

Here’s the first change. We have to modify our entity to accommodate another VECTORdata type column, that is, embedding_two. It’s a minor adjustment anyway, so please just add it. Given that using Java Records with Hibernate has some limitations, we’ll add the respective setters/getters as expected as well.

@Entity
@Table(name = "VECTOR_USER.vector_data_search")
public class HibernateVectorDataTypeEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "embedding")
@JdbcTypeCode(SqlTypes.VECTOR_FLOAT32)
@Array(length = 3)
private float[] embedding;

@Column(name = "embedding_two")
@JdbcTypeCode(SqlTypes.VECTOR_FLOAT32)
@Array(length = 3)
private float[] embeddingTwo;

Step 4: Storing and Retrieving Vector Embeddings

Once your entity is set up, you can store and retrieve vectors using Hibernate as explained in Part 1 as well — so all methods are the same except the insertVector() method which has been modified to support the inserts that consider the second column now.

Insert vector

  private void insertVector() {
try (Session session = sessionFactory.openSession()) {
Transaction tx = session.beginTransaction();
HibernateVectorDataTypeEntity entity = new HibernateVectorDataTypeEntity();

float[] emb1 = { randFloat(), randFloat(), randFloat() };
float[] emb2 = { randFloat(), randFloat(), randFloat() };

entity.setEmbedding(emb1);
entity.setEmbeddingTwo(emb2);

session.persist(entity);
tx.commit();
}
}

Note that values will be created by a helper method called randFloat(), as it will generate values from a normal distribution centered at 0 with a considerable spread between [-50, 50]. This is interesting because to demonstrate the similarity searches, we do not want all vectors to be the same, or pretty similar.

  private float randFloat() {    
return (float) (Math.random() * 100 - 50);
}

All remaining Java methods that work directly with Hibernate and data (readVector(), updateVector(), and deleteVector()) have similar implementations as explained in Part 1, and some utility methods have been added as required.

Step 5: Oracle AI Vector Search with Hibernate Vector

As cited before, you can still use HQL (Hibernate Query Language) combined with several functions as the Hibernate Vector module implementation maps to the underlying Oracle AI Vector Search functions.

Below is the list of supported functions (not an exhaustive list).

Last but not least, let’s have a look at how to use them from your Java code.

Similarity search with cosine_distance()

  public void cosineSimilaritySearch(float[] searchVector) {
try (Session session = sessionFactory.openSession()) {
Query<HibernateVectorDataTypeEntity> query = session.createQuery(
"SELECT e FROM HibernateVectorDataTypeEntity e " + "ORDER BY cosine_distance(e.embedding, :vector) ASC",
HibernateVectorDataTypeEntity.class);
query.setParameter("vector", searchVector);
List<HibernateVectorDataTypeEntity> results = query.getResultList();

System.out.println("\nCosine Similarity Results:");
results.forEach(e -> System.out.println("ID: " + e.getId() + " - " + Arrays.toString(e.getEmbedding())));
}
}

Similarity search with l1_distance()

  public void l1DistanceSearch(float[] searchVector) {
try (Session session = sessionFactory.openSession()) {
Query<HibernateVectorDataTypeEntity> query = session.createQuery(
"SELECT e FROM HibernateVectorDataTypeEntity e " + "ORDER BY l1_distance(e.embedding, :vector) ASC",
HibernateVectorDataTypeEntity.class);
query.setParameter("vector", searchVector);
List<HibernateVectorDataTypeEntity> results = query.getResultList();

System.out.println("\nL1 Distance Results:");
results.forEach(e -> System.out.println("ID: " + e.getId() + " - " + Arrays.toString(e.getEmbedding())));
}
}

Similarity search with l2_distance()

  public void l2DistanceSearch(float[] searchVector) {
try (Session session = sessionFactory.openSession()) {
Query<HibernateVectorDataTypeEntity> query = session.createQuery(
"SELECT e FROM HibernateVectorDataTypeEntity e " + "ORDER BY l2_distance(e.embedding, :vector) ASC",
HibernateVectorDataTypeEntity.class);
query.setParameter("vector", searchVector);
List<HibernateVectorDataTypeEntity> results = query.getResultList();

System.out.println("\nL2 Distance Results:");
results.forEach(e -> System.out.println("ID: " + e.getId() + " - " + Arrays.toString(e.getEmbedding())));
}
}

Step 6: Test the sample app

Now, you can run and test the application using your preferred IDE (or the CLI). You may want to set breakpoints to query the database and check the records.

Besides, you may enable query debugging if you want to have a look at the underlying HQL queries. As cited in Part 1, just go to your hibernate.properties file and change hibernate.show_sql from false to true.

Note that this time, we inserted 100 records as we needed a larger dataset to exercise the similarity vector searches properly, as shown below.

Hibernate Vector — 100 records inserted

Next, you will see the results of the same similiarty searches we explained before (Java methods/code above).

Similarity search — cosine_distance() results

Similarity search — cosine_distance() results

Similarity search — l1_distance() results

Similarity search — l1_distance() results

Similarity search — l2_distance() results

Similarity search — l2_distance() results

Delete all vectors (database cleanup)

As one last step, we will delete all the records by using a helper Java method called cleanDatabase(), as show below.

Delete all records with cleanDatabase()

Code sample

Below is the complete source code so you can give it a try!

HibernateVectorDataTypeEntity.java

HibernateVectorDataTypeOracleDatabase.java

Wrap-Up

That’s it! This blog post presented a combination of the Hibernate Vector module, Jakarta Persistence, and Oracle AI Vector Search, exploring how they can easily enable the creation of GenAI solutions. As we learned, Java developers now have an easy way to handle vector data and enable vector similarity searches, ultimately improving their productivity and the time-to-market of their applications!

As one last tip, I invite you to check out the new Database Navigator tool published at JetBrains Marketplace. In a nutshell, it features a robust SQL and PL/SQL editor with advanced capabilities for managing database connections, executing scripts, editing database objects, and modifying data and code with IntelliJ!

I will soon post more examples of scenarios involving LangChain4J, the OracleEmbeddingStore, GraalVM, Micronaut, Quarkus, and other GenAI / Agentic AI-related topics!

That’s it! I hope you liked this blog post, thanks for reading!

References

Hibernate 6.6

Overview of Oracle AI Vector Search

Oracle AI Vector Search Technical Architecture

Building AI-Powered Database Apps with Hibernate Vector and the Oracle Database 23ai — Part 1 — Using Hibernate Vector module with Oracle Vector Data Type

Jakarta Persistence

Oracle Database 23ai

Oracle Database Free Release 23ai — Container Image

Oracle JDBC Driver 23ai (23.4+) — Maven Central

Oracle® Database JDBC Java API Reference, Release 23ai

Database Navigator — JetBrains Marketplace

Quickstart: Connect to Oracle Database 23ai using IntelliJ IDEA

Developers Guide For Oracle JDBC on Maven Central

Develop Java applications with Oracle Database

Oracle Developers and Oracle OCI Free Tier

Join our Oracle Developers channel on Slack to discuss Java, GenAI, Agentic AI, JDK, JDBC, GraalVM, Micronaut, Spring Boot, Helidon, Quarkus, Reactive Streams, Cloud, DevOps, SRE, IaC, and other topics!

Build, test, and deploy your applications on Oracle Cloud — for free! Get access to OCI Cloud Free Tier!

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

No responses yet

Write a response