diff --git a/memory/repository/spring-ai-model-chat-memory-repository-jdbc/pom.xml b/memory/repository/spring-ai-model-chat-memory-repository-jdbc/pom.xml
index 4eea9995759..38d51b12103 100644
--- a/memory/repository/spring-ai-model-chat-memory-repository-jdbc/pom.xml
+++ b/memory/repository/spring-ai-model-chat-memory-repository-jdbc/pom.xml
@@ -50,13 +50,7 @@
spring-jdbc
-
- com.zaxxer
- HikariCP
-
-
-
org.postgresql
postgresql
@@ -85,6 +79,20 @@
true
+
+
+ com.oracle.database.jdbc
+ ojdbc11
+ 23.9.0.25.07
+ test
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+ test
+
+
org.xerial
sqlite-jdbc
@@ -111,6 +119,14 @@
test
+
+
+ org.testcontainers
+ oracle-xe
+ 1.19.0
+ test
+
+
org.testcontainers
postgresql
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/main/java/org/springframework/ai/chat/memory/repository/jdbc/JdbcChatMemoryRepositoryDialect.java b/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/main/java/org/springframework/ai/chat/memory/repository/jdbc/JdbcChatMemoryRepositoryDialect.java
index 0b9cf1b73ce..22a1d8cf6c2 100644
--- a/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/main/java/org/springframework/ai/chat/memory/repository/jdbc/JdbcChatMemoryRepositoryDialect.java
+++ b/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/main/java/org/springframework/ai/chat/memory/repository/jdbc/JdbcChatMemoryRepositoryDialect.java
@@ -74,6 +74,7 @@ static JdbcChatMemoryRepositoryDialect from(DataSource dataSource) {
case "MySQL", "MariaDB" -> new MysqlChatMemoryRepositoryDialect();
case "Microsoft SQL Server" -> new SqlServerChatMemoryRepositoryDialect();
case "HSQL Database Engine" -> new HsqldbChatMemoryRepositoryDialect();
+ case "Oracle" -> new OracleChatMemoryRepositoryDialect();
case "SQLite" -> new SqliteChatMemoryRepositoryDialect();
case "H2" -> new H2ChatMemoryRepositoryDialect();
default -> // Add more as needed
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/main/java/org/springframework/ai/chat/memory/repository/jdbc/OracleChatMemoryRepositoryDialect.java b/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/main/java/org/springframework/ai/chat/memory/repository/jdbc/OracleChatMemoryRepositoryDialect.java
new file mode 100644
index 00000000000..a3784509c6e
--- /dev/null
+++ b/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/main/java/org/springframework/ai/chat/memory/repository/jdbc/OracleChatMemoryRepositoryDialect.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2024-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ai.chat.memory.repository.jdbc;
+
+/**
+ * Dialect for Oracle.
+ *
+ * @author Xiaotong Fan
+ * @since 1.1.0
+ */
+
+public class OracleChatMemoryRepositoryDialect implements JdbcChatMemoryRepositoryDialect {
+
+ @Override
+ public String getSelectMessagesSql() {
+ return "SELECT content, type FROM SPRING_AI_CHAT_MEMORY WHERE CONVERSATION_ID = ? ORDER BY \"TIMESTAMP\"";
+ }
+
+ @Override
+ public String getInsertMessageSql() {
+ return "INSERT INTO SPRING_AI_CHAT_MEMORY (CONVERSATION_ID, CONTENT, TYPE, \"TIMESTAMP\") VALUES (?, ?, ?, ?)";
+ }
+
+ @Override
+ public String getSelectConversationIdsSql() {
+ return "SELECT DISTINCT conversation_id FROM SPRING_AI_CHAT_MEMORY";
+ }
+
+ @Override
+ public String getDeleteMessagesSql() {
+ return "DELETE FROM SPRING_AI_CHAT_MEMORY WHERE CONVERSATION_ID = ?";
+ }
+
+}
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/main/resources/org/springframework/ai/chat/memory/repository/jdbc/schema-oracle.sql b/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/main/resources/org/springframework/ai/chat/memory/repository/jdbc/schema-oracle.sql
new file mode 100644
index 00000000000..47a411299b5
--- /dev/null
+++ b/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/main/resources/org/springframework/ai/chat/memory/repository/jdbc/schema-oracle.sql
@@ -0,0 +1,21 @@
+DROP TABLE SPRING_AI_CHAT_MEMORY;
+
+CREATE TABLE SPRING_AI_CHAT_MEMORY (
+ CONVERSATION_ID VARCHAR2(36 CHAR) NOT NULL,
+ CONTENT CLOB NOT NULL,
+ "TYPE" VARCHAR2(10 CHAR) NOT NULL CHECK (
+ "TYPE" IN (
+ 'USER',
+ 'ASSISTANT',
+ 'SYSTEM',
+ 'TOOL'
+ )
+ ),
+ "TIMESTAMP" TIMESTAMP NOT NULL
+);
+
+CREATE INDEX SPRING_AI_CHAT_MEMORY_CONVERSATION_ID_TIMESTAMP_IDX
+ ON SPRING_AI_CHAT_MEMORY(
+ CONVERSATION_ID,
+ 'TIMESTAMP'
+ );
\ No newline at end of file
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/chat/memory/repository/jdbc/JdbcChatMemoryRepositoryBuilderTests.java b/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/chat/memory/repository/jdbc/JdbcChatMemoryRepositoryBuilderTests.java
index 87dbfa5f03b..80f6a97f156 100644
--- a/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/chat/memory/repository/jdbc/JdbcChatMemoryRepositoryBuilderTests.java
+++ b/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/chat/memory/repository/jdbc/JdbcChatMemoryRepositoryBuilderTests.java
@@ -37,6 +37,7 @@
*
* @author Mark Pollack
* @author Yanming Zhou
+ * @author Xiaotong Fan
*/
public class JdbcChatMemoryRepositoryBuilderTests {
@@ -136,6 +137,23 @@ void testBuilderWithHsqldbDialectFromDataSource() throws SQLException {
assertThat(repository).isNotNull();
}
+ @Test
+ void testBuilderWithOracleDialectFromDataSource() throws SQLException {
+ // Setup mocks for Oracle
+ DataSource dataSource = mock(DataSource.class);
+ Connection connection = mock(Connection.class);
+ DatabaseMetaData metaData = mock(DatabaseMetaData.class);
+
+ when(dataSource.getConnection()).thenReturn(connection);
+ when(connection.getMetaData()).thenReturn(metaData);
+ when(metaData.getURL()).thenReturn("jdbc:oracle:thin:@//192.168.19.129:1521/ORCL");
+
+ // Test with dialect from datasource
+ JdbcChatMemoryRepository repository = JdbcChatMemoryRepository.builder().dataSource(dataSource).build();
+
+ assertThat(repository).isNotNull();
+ }
+
@Test
void testBuilderWithUnknownDialectFromDataSource() throws SQLException {
// Setup mocks for unknown database
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/chat/memory/repository/jdbc/JdbcChatMemoryRepositoryOracleIT.java b/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/chat/memory/repository/jdbc/JdbcChatMemoryRepositoryOracleIT.java
new file mode 100644
index 00000000000..511967d9ee8
--- /dev/null
+++ b/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/chat/memory/repository/jdbc/JdbcChatMemoryRepositoryOracleIT.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2023-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ai.chat.memory.repository.jdbc;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.jdbc.Sql;
+
+/**
+ * Integration tests for {@link JdbcChatMemoryRepository} with Oracle.
+ *
+ * @author Xiaotong Fan
+ */
+
+@SpringBootTest
+@TestPropertySource(properties = { "spring.datasource.url=jdbc:oracle:thin:@localhost:1521/FREEPDB1",
+ "spring.datasource.username=scott", "spring.datasource.password=tiger" })
+@Sql(scripts = "classpath:org/springframework/ai/chat/memory/repository/jdbc/schema-oracle.sql")
+public class JdbcChatMemoryRepositoryOracleIT extends AbstractJdbcChatMemoryRepositoryIT {
+
+}
diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat-memory.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat-memory.adoc
index 4231a2dbcb6..18b28a15969 100644
--- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat-memory.adoc
+++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat-memory.adoc
@@ -128,6 +128,7 @@ Spring AI supports multiple relational databases via a dialect abstraction. The
- MySQL / MariaDB
- SQL Server
- HSQLDB
+- Oracle Database
The correct dialect can be auto-detected from the JDBC URL when using `JdbcChatMemoryRepositoryDialect.from(DataSource)`. You can extend support for other databases by implementing the `JdbcChatMemoryRepositoryDialect` interface.