Skip to content

Commit 30af4e8

Browse files
fanxt0218psilberk
authored andcommitted
Adapt Oracle JDBC ChatMemoryRepository support
- Add Oracle Dialect and Schema - Update docs and tests Signed-off-by: fanxt0218 <[email protected]> Co-authored-by: psilberk <[email protected]>
1 parent 4273328 commit 30af4e8

File tree

7 files changed

+146
-1
lines changed

7 files changed

+146
-1
lines changed

memory/repository/spring-ai-model-chat-memory-repository-jdbc/pom.xml

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@
5656
</dependency>
5757

5858
<!-- TESTING -->
59-
6059
<dependency>
6160
<groupId>org.postgresql</groupId>
6261
<artifactId>postgresql</artifactId>
@@ -99,6 +98,20 @@
9998
<optional>true</optional>
10099
</dependency>
101100

101+
<dependency>
102+
<groupId>com.oracle.database.jdbc</groupId>
103+
<artifactId>ojdbc11</artifactId>
104+
<version>23.4.0.24.05</version>
105+
<scope>test</scope>
106+
<optional>true</optional>
107+
</dependency>
108+
109+
<dependency>
110+
<groupId>org.springframework.boot</groupId>
111+
<artifactId>spring-boot-starter-jdbc</artifactId>
112+
<scope>test</scope>
113+
</dependency>
114+
102115
<dependency>
103116
<groupId>org.springframework.boot</groupId>
104117
<artifactId>spring-boot-starter-test</artifactId>
@@ -111,6 +124,13 @@
111124
<scope>test</scope>
112125
</dependency>
113126

127+
<dependency>
128+
<groupId>org.testcontainers</groupId>
129+
<artifactId>testcontainers-oracle-free</artifactId>
130+
<version>2.0.1</version>
131+
<scope>test</scope>
132+
</dependency>
133+
114134
<dependency>
115135
<groupId>org.testcontainers</groupId>
116136
<artifactId>postgresql</artifactId>

memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/main/java/org/springframework/ai/chat/memory/repository/jdbc/JdbcChatMemoryRepositoryDialect.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ static JdbcChatMemoryRepositoryDialect from(DataSource dataSource) {
7676
case "HSQL Database Engine" -> new HsqldbChatMemoryRepositoryDialect();
7777
case "SQLite" -> new SqliteChatMemoryRepositoryDialect();
7878
case "H2" -> new H2ChatMemoryRepositoryDialect();
79+
case "Oracle" -> new OracleChatMemoryRepositoryDialect();
7980
default -> // Add more as needed
8081
new PostgresChatMemoryRepositoryDialect();
8182
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2025-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.ai.chat.memory.repository.jdbc;
18+
19+
/**
20+
* Dialect for Oracle.
21+
*
22+
* @author Xiaotong Fan
23+
* @author Pablo Silberkasten
24+
* @since 1.1.0
25+
*/
26+
27+
public class OracleChatMemoryRepositoryDialect implements JdbcChatMemoryRepositoryDialect {
28+
29+
@Override
30+
public String getSelectMessagesSql() {
31+
return "SELECT content, type FROM SPRING_AI_CHAT_MEMORY WHERE CONVERSATION_ID = ? ORDER BY \"TIMESTAMP\"";
32+
}
33+
34+
@Override
35+
public String getInsertMessageSql() {
36+
return "INSERT INTO SPRING_AI_CHAT_MEMORY (CONVERSATION_ID, CONTENT, TYPE, \"TIMESTAMP\") VALUES (?, ?, ?, ?)";
37+
}
38+
39+
@Override
40+
public String getSelectConversationIdsSql() {
41+
return "SELECT DISTINCT conversation_id FROM SPRING_AI_CHAT_MEMORY";
42+
}
43+
44+
@Override
45+
public String getDeleteMessagesSql() {
46+
return "DELETE FROM SPRING_AI_CHAT_MEMORY WHERE CONVERSATION_ID = ?";
47+
}
48+
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
DROP TABLE IF EXISTS SPRING_AI_CHAT_MEMORY;
2+
3+
CREATE TABLE SPRING_AI_CHAT_MEMORY (
4+
CONVERSATION_ID VARCHAR2(36 CHAR) NOT NULL,
5+
CONTENT CLOB NOT NULL,
6+
"TYPE" VARCHAR2(10 CHAR) NOT NULL CHECK (
7+
"TYPE" IN (
8+
'USER',
9+
'ASSISTANT',
10+
'SYSTEM',
11+
'TOOL'
12+
)
13+
),
14+
"TIMESTAMP" TIMESTAMP NOT NULL
15+
);
16+
17+
CREATE INDEX SPRING_AI_CHAT_MEMORY_CONVERSATION_ID_TIMESTAMP_IDX
18+
ON SPRING_AI_CHAT_MEMORY(
19+
CONVERSATION_ID,
20+
'TIMESTAMP'
21+
);

memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/chat/memory/repository/jdbc/JdbcChatMemoryRepositoryBuilderTests.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
*
3838
* @author Mark Pollack
3939
* @author Yanming Zhou
40+
* @author Xiaotong Fan
4041
*/
4142
public class JdbcChatMemoryRepositoryBuilderTests {
4243

@@ -136,6 +137,23 @@ void testBuilderWithHsqldbDialectFromDataSource() throws SQLException {
136137
assertThat(repository).isNotNull();
137138
}
138139

140+
@Test
141+
void testBuilderWithOracleDialectFromDataSource() throws SQLException {
142+
// Setup mocks for Oracle
143+
DataSource dataSource = mock(DataSource.class);
144+
Connection connection = mock(Connection.class);
145+
DatabaseMetaData metaData = mock(DatabaseMetaData.class);
146+
147+
when(dataSource.getConnection()).thenReturn(connection);
148+
when(connection.getMetaData()).thenReturn(metaData);
149+
when(metaData.getURL()).thenReturn("jdbc:oracle:thin:@//192.168.19.129:1521/ORCL");
150+
151+
// Test with dialect from datasource
152+
JdbcChatMemoryRepository repository = JdbcChatMemoryRepository.builder().dataSource(dataSource).build();
153+
154+
assertThat(repository).isNotNull();
155+
}
156+
139157
@Test
140158
void testBuilderWithUnknownDialectFromDataSource() throws SQLException {
141159
// Setup mocks for unknown database
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2023-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.ai.chat.memory.repository.jdbc;
18+
19+
import org.springframework.boot.test.context.SpringBootTest;
20+
import org.springframework.test.context.TestPropertySource;
21+
import org.springframework.test.context.jdbc.Sql;
22+
23+
/**
24+
* Integration tests for {@link JdbcChatMemoryRepository} with Oracle.
25+
*
26+
* @author Xiaotong Fan
27+
*/
28+
29+
@SpringBootTest
30+
@TestPropertySource(properties = { "spring.datasource.url=jdbc:tc:oracle:slim-faststart:///FREEPDB1",
31+
"spring.datasource.username=test", "spring.datasource.password=test" })
32+
@Sql(scripts = "classpath:org/springframework/ai/chat/memory/repository/jdbc/schema-oracle.sql")
33+
public class JdbcChatMemoryRepositoryOracleIT extends AbstractJdbcChatMemoryRepositoryIT {
34+
35+
}

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat-memory.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ Spring AI supports multiple relational databases via a dialect abstraction. The
128128
- MySQL / MariaDB
129129
- SQL Server
130130
- HSQLDB
131+
- Oracle Database
131132

132133
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.
133134

0 commit comments

Comments
 (0)