Skip to content

Commit 875b24a

Browse files
committed
Optimize support for multiple data sources and add additional test cases.
1 parent 8d4045f commit 875b24a

File tree

4 files changed

+283
-83
lines changed

4 files changed

+283
-83
lines changed

langchain4j-pgvector-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/pgvector/spring/PgVectorDataSourceProperties.java

Lines changed: 11 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -3,85 +3,20 @@
33
import org.springframework.boot.context.properties.ConfigurationProperties;
44

55
@ConfigurationProperties(prefix = PgVectorDataSourceProperties.PREFIX)
6-
public class PgVectorDataSourceProperties {
7-
6+
public record PgVectorDataSourceProperties(
7+
boolean enabled,
8+
String host,
9+
String user,
10+
String password,
11+
Integer port,
12+
String database
13+
) {
814
static final String PREFIX = "langchain4j.pgvector.datasource";
915

1016
/**
11-
* Enable postgres datasource configuration, default value <code>false</code>.
12-
*/
13-
private boolean enabled = false;
14-
15-
/**
16-
* The pgvector database host.
17-
*/
18-
private String host;
19-
20-
/**
21-
* The pgvector database user.
22-
*/
23-
private String user;
24-
25-
/**
26-
* The pgvector database password.
17+
* Provide a default constructor that sets the default value of enabled to false.
2718
*/
28-
private String password;
29-
30-
/**
31-
* The pgvector database port.
32-
*/
33-
private Integer port;
34-
35-
/**
36-
* The pgvector database name.
37-
*/
38-
private String database;
39-
40-
public boolean isEnabled() {
41-
return enabled;
42-
}
43-
44-
public void setEnabled(boolean enabled) {
45-
this.enabled = enabled;
46-
}
47-
48-
public String getHost() {
49-
return host;
50-
}
51-
52-
public void setHost(String host) {
53-
this.host = host;
54-
}
55-
56-
public String getUser() {
57-
return user;
58-
}
59-
60-
public void setUser(String user) {
61-
this.user = user;
62-
}
63-
64-
public String getPassword() {
65-
return password;
66-
}
67-
68-
public void setPassword(String password) {
69-
this.password = password;
70-
}
71-
72-
public Integer getPort() {
73-
return port;
74-
}
75-
76-
public void setPort(Integer port) {
77-
this.port = port;
78-
}
79-
80-
public String getDatabase() {
81-
return database;
82-
}
83-
84-
public void setDatabase(String database) {
85-
this.database = database;
19+
public PgVectorDataSourceProperties() {
20+
this(false, null, null, null, null, null);
8621
}
8722
}

langchain4j-pgvector-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/pgvector/spring/PgVectorEmbeddingStoreAutoConfiguration.java

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,21 @@
44
import dev.langchain4j.store.embedding.pgvector.PgVectorEmbeddingStore;
55
import org.slf4j.Logger;
66
import org.slf4j.LoggerFactory;
7+
import org.springframework.beans.factory.ObjectProvider;
78
import org.springframework.boot.autoconfigure.AutoConfiguration;
89
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
910
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
1011
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
1112
import org.springframework.boot.context.properties.EnableConfigurationProperties;
13+
import org.springframework.context.ApplicationContext;
1214
import org.springframework.context.annotation.Bean;
1315
import org.springframework.lang.Nullable;
1416

1517
import javax.sql.DataSource;
1618
import java.sql.Connection;
1719
import java.sql.DatabaseMetaData;
1820
import java.sql.SQLException;
21+
import java.util.Map;
1922
import java.util.Optional;
2023

2124
import static dev.langchain4j.internal.ValidationUtils.*;
@@ -29,12 +32,40 @@ public class PgVectorEmbeddingStoreAutoConfiguration {
2932

3033
private static final Logger log = LoggerFactory.getLogger(PgVectorEmbeddingStoreAutoConfiguration.class);
3134

35+
private final ApplicationContext applicationContext;
36+
37+
public PgVectorEmbeddingStoreAutoConfiguration(ApplicationContext applicationContext) {
38+
this.applicationContext = applicationContext;
39+
}
40+
3241
@Bean
3342
@ConditionalOnMissingBean
3443
@ConditionalOnBean(DataSource.class)
3544
@ConditionalOnProperty(prefix = PgVectorDataSourceProperties.PREFIX, name = "enabled", havingValue = "false")
36-
public PgVectorEmbeddingStore pgVectorEmbeddingStoreWithExistingDataSource(DataSource dataSource, PgVectorEmbeddingStoreProperties properties,
37-
@Nullable EmbeddingModel embeddingModel) {
45+
public PgVectorEmbeddingStore pgVectorEmbeddingStoreWithExistingDataSource(ObjectProvider<DataSource> dataSources, PgVectorEmbeddingStoreProperties properties,
46+
@Nullable EmbeddingModel embeddingModel) {
47+
48+
// The PostgreSQL data source is selected based on the configured dataSourceBeanName or automatically.
49+
DataSource dataSource = dataSources.stream()
50+
.filter(ds -> {
51+
// Preferentially matches the configured dataSourceBeanName.
52+
String beanName = properties.getDataSourceBeanName();
53+
if (beanName != null && !beanName.isEmpty()) {
54+
String actualBeanName = getBeanNameForDataSource(ds);
55+
return beanName.equals(actualBeanName);
56+
}
57+
return false;
58+
})
59+
.findFirst()
60+
// If no dataSourceBeanName is specified, the first PostgreSQL data source is selected.
61+
.orElseGet(() -> dataSources.stream()
62+
.filter(this::isPostgresqlDataSource)
63+
.findFirst()
64+
.orElseThrow(() -> new IllegalStateException("No suitable PostgreSQL DataSource found in the application context. "
65+
+ "Please configure a valid PostgreSQL DataSource.")));
66+
67+
log.info("Using DataSource bean: {}", dataSource.getClass().getSimpleName());
68+
3869
// Check if the context's data source is a Postgres datasource
3970
ensureTrue(isPostgresqlDataSource(dataSource), "The DataSource in Spring Context is not a Postgres datasource, you need to manually specify the Postgres datasource configuration via 'langchain4j.pgvector.datasource'.");
4071

@@ -58,11 +89,11 @@ public PgVectorEmbeddingStore pgVectorEmbeddingStoreWithCustomDataSource(PgVecto
5889
Integer dimension = Optional.ofNullable(properties.getDimension()).orElseGet(() -> embeddingModel == null ? null : embeddingModel.dimension());
5990

6091
return PgVectorEmbeddingStore.builder()
61-
.host(dataSourceProperties.getHost())
62-
.port(dataSourceProperties.getPort())
63-
.user(dataSourceProperties.getUser())
64-
.password(dataSourceProperties.getPassword())
65-
.database(dataSourceProperties.getDatabase())
92+
.host(dataSourceProperties.host())
93+
.port(dataSourceProperties.port())
94+
.user(dataSourceProperties.user())
95+
.password(dataSourceProperties.password())
96+
.database(dataSourceProperties.database())
6697
.table(properties.getTable())
6798
.createTable(properties.getCreateTable())
6899
.dimension(dimension)
@@ -85,4 +116,18 @@ private boolean isPostgresqlDataSource(DataSource dataSource) {
85116
return false;
86117
}
87118
}
119+
120+
/**
121+
* Get the BeanName of the DataSource instance from the ApplicationContext.
122+
* @param dataSource Target DataSource instance.
123+
* @return bean name of target DataSource .
124+
*/
125+
private String getBeanNameForDataSource(DataSource dataSource) {
126+
// 遍历所有 DataSource Bean,找到与当前实例匹配的 Bean 名称
127+
return applicationContext.getBeansOfType(DataSource.class).entrySet().stream()
128+
.filter(entry -> entry.getValue().equals(dataSource))
129+
.map(Map.Entry::getKey)
130+
.findFirst()
131+
.orElse(null);
132+
}
88133
}

langchain4j-pgvector-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/pgvector/spring/PgVectorEmbeddingStoreProperties.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ public class PgVectorEmbeddingStoreProperties {
3232
*/
3333
private Integer indexListSize;
3434

35+
private String dataSourceBeanName;
36+
37+
3538
public String getTable() {
3639
return table;
3740
}
@@ -71,4 +74,12 @@ public Integer getIndexListSize() {
7174
public void setIndexListSize(Integer indexListSize) {
7275
this.indexListSize = indexListSize;
7376
}
77+
78+
public String getDataSourceBeanName() {
79+
return dataSourceBeanName;
80+
}
81+
82+
public void setDataSourceBeanName(String dataSourceBeanName) {
83+
this.dataSourceBeanName = dataSourceBeanName;
84+
}
7485
}

0 commit comments

Comments
 (0)