LangChain4j Hibernate 集成实战:在任意 Hibernate 支持数据库中构建向量检索与 RAG
2026/9/15 17:20:51 网站建设 项目流程

LangChain4j Hibernate 集成实战:在任意 Hibernate 支持数据库中构建向量检索与 RAG

【免费下载链接】langchain4jLangChain4j is an idiomatic, open-source Java library for building LLM-powered applications on the JVM. It offers a unified API over popular LLM providers and vector stores, and makes implementing tool calling (including MCP support), agents and RAG easy. It integrates seamlessly with enterprise Java frameworks like Quarkus and Spring Boot.项目地址: https://gitcode.com/GitHub_Trending/la/langchain4j

本文是 LangChain4j Hibernate 向量存储集成(langchain4j-hibernate)的完整实战指南。该模块将 LangChain4j 的EmbeddingStoreAPI 与 Hibernate ORM 无缝打通,使开发者可以直接在 Hibernate 支持的所有数据库(PostgreSQL、MySQL、MariaDB、DB2、SQL Server、Oracle、CockroachDB、SAP HANA 等)中存取与查询向量嵌入,进而用于语义搜索、RAG 等场景。读完本文,你将掌握两种存储构建模式(动态通用存储与实体存储)的全部配置参数、自定义 Hibernate 实体的注解用法、基于 PGVector 的完整 RAG 落地示例,以及多数据库向量索引 DDL 与生产级调优建议。

集成概览:为什么选择 Hibernate 作为向量存储层

LangChain4j 的 Hibernate 集成允许开发者将向量嵌入(embedding)直接存储并查询到 Hibernate 支持的所有数据库,无需引入额外的独立向量数据库。对于已经基于 Hibernate 管理数据模型的企业级 Java 应用(尤其是 Quarkus、Spring Boot 生态),这意味着可以复用现有的SessionFactory、实体映射、事务与连接池设施,在同一套数据基础设施中同时完成业务数据与向量数据的持久化。

从仓库源码看,该模块位于 langchain4j-hibernate,其核心 API 只有两类:

  • HibernateEmbeddingStore:实现 LangChain4j 的EmbeddingStore<TextSegment>接口,负责向量的增、删、查(含相似度检索与元数据过滤)。
  • 四个注解:@EmbeddingVector@EmbeddedText@UnmappedMetadata@MetadataAttribute,用于在自定义实体上标注向量存储所需的字段。

模块依赖方面,langchain4j-hibernate/pom.xml 显示其依赖langchain4j-corehibernate-corehibernate-vector(当前使用 Hibernate ORM 7.4.2.Final),并在测试中借助 Testcontainers 覆盖 PostgreSQL/PGVector、DB2、Oracle、MariaDB、SQL Server、CockroachDB 等多种数据库,集成测试类位于 langchain4j-hibernate/src/test/java/dev/langchain4j/store/embedding 下的generictyped两个包。

添加依赖

在项目中引入langchain4j-hibernate(以下为官方文档示例版本):

<dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-hibernate</artifactId> <version>1.20.0-beta30</version> </dependency>

使用 Gradle 则对应:

implementation 'dev.langchain4j:langchain4j-hibernate:1.20.0-beta30'

注意:仓库当前源码版本为1.21.0-beta31-SNAPSHOT(见 langchain4j-hibernate/pom.xml),实际使用时请以你依赖的发行版本为准。该模块还需要你自行引入对应数据库的 JDBC 驱动,并可选用连接池(如 HikariCP)以提升生产环境表现。

两种构建模式:Generic Store 与 Entity Store

HibernateEmbeddingStore提供了两种构建入口,分别对应不同的使用诉求:

模式构建入口适用场景
Generic Store(通用存储)HibernateEmbeddingStore.dynamicBuilder()/dynamicDatasourceBuilder()只关心EmbeddingStoreAPI,不想操心实体类定义与 Hibernate 配置细节
Entity Store(实体存储)HibernateEmbeddingStore.builder()希望复用已有的 Hibernate 实体模型,或需要对数据模型做定制

两种模式的核心差异在于"表结构由谁定义":Generic Store 由 store 内部动态生成 Hibernate 元模型与建表逻辑,用户只需提供连接参数、表名与向量维度;Entity Store 则完全基于你传入的实体类(及其上的注解)来映射表结构。

Generic Store 参数详解

Generic Store 的参数通过两种 builder 变体提供:

  • dynamicBuilder():以jdbcUrlhost/port/database+user/password直接描述数据库连接。
  • dynamicDatasourceBuilder():直接注入一个现成的DataSource对象(推荐用于生产环境,配合连接池)。

完整参数如下:

Plain Java Property说明默认值必填/可选
datasource数据库连接的DataSource对象。仅在dynamicDatasourceBuilder()变体中可用。若未提供,则必须在dynamicBuilder()变体中单独提供jdbcUrluserpasswordjdbcUrluserpassword二选一必填
jdbcUrl数据库服务器的 JDBC URL。仅在dynamicBuilder()变体中可用。若未提供DataSourcehostportdatabase,则必填。三选一必填
host数据库服务器主机名。仅在dynamicBuilder()变体中可用。若DataSourcejdbcUrl均未提供,则必填。三选一必填
port数据库服务器端口。仅在dynamicBuilder()变体中可用。若DataSourcejdbcUrl均未提供,则必填。三选一必填
database要连接的数据库名。仅在dynamicBuilder()变体中可用。若DataSourcejdbcUrl均未提供,则必填。三选一必填
databaseKind数据库类型。若提供了DataSource,或无法从jdbcUrl推断出类型时,则必填。特定条件下必填
user数据库认证用户名。仅在dynamicBuilder()变体中可用。若未提供DataSource,则必填。条件必填
password数据库认证密码。仅在dynamicBuilder()变体中可用。若未提供DataSource,则必填。条件必填
table存储嵌入的数据库表名。必填
dimension嵌入向量的维度,须与所用嵌入模型一致。可用embeddingModel.dimension()动态设置。必填
createIndex是否自动为向量嵌入创建索引。false可选
indexType数据库特定的索引类型,如ivfflathnsw。IVFFlat 将向量划分为若干列表(lists),查询时只搜索与查询向量最接近的一部分列表;相比 HNSW,其建索引更快、内存占用更少,但在查询性能(速度与召回率的权衡)上较低。PostgreSQL 上建议使用 IVFFlat 索引。无(默认使用数据库偏好类型,如 PostgreSQL 上的ivfflat可选
indexOptions配置在向量索引上的选项。当createIndex=true且索引类型为ivfflat时:PostgreSQL 上必须提供lists = 1且取值必须大于零,否则表初始化阶段会抛出异常。当createIndex=false时该参数被忽略,无需设置。条件必填/可选
createTable是否自动创建嵌入表。false可选
dropTableFirst是否在重建表前先删除旧表(适合测试场景)。false可选
distanceFunction向量搜索所用的距离函数,支持范围因数据库而异:COSINEEUCLIDEANEUCLIDEAN_SQUAREDMANHATTANINNER_PRODUCTNEGATIVE_INNER_PRODUCTHAMMINGJACCARDCOSINE可选(未设置时默认使用COSINE

关于databaseKind的取值,源码 DatabaseKind.java 定义了 8 种枚举常量:DB2MARIADBMSSQLMYSQLPOSTGRESQLCOCKROACHDBORACLEHANA。当使用jdbcUrl时,determineDatabaseKind(String jdbcUrl)会自动识别数据库类型;当使用DataSource或实体模式时,则可通过determineDatabaseKind(Dialect)从 Hibernate 方言推断;推断不出时才需要手动指定。

需要特别指出:并非所有距离函数在所有数据库上都可用。从 DatabaseKind.java 的实现可以看出,例如 MariaDB 只支持COSINEEUCLIDEAN,传入其他值会直接抛出IllegalArgumentException;SQL Server 不支持MANHATTANHAMMINGJACCARD;CockroachDB 不支持MANHATTANHAMMINGJACCARD;SAP HANA 仅支持COSINEEUCLIDEAN。因此设置distanceFunction前务必对照所选数据库的向量能力。

Entity Store 参数详解

Entity Store 使用HibernateEmbeddingStore.builder()构建,直接对接已有实体模型:

Plain Java Property说明默认值必填/可选
sessionFactory包含entityClassSessionFactory对象。必填
databaseKind数据库类型。若无法从 Hibernate ORM 方言推断出类型,则必填。条件必填
entityClass用于EmbeddingStore的实体类(属于上述SessionFactory)。必填
embeddingAttributeName表示向量嵌入的实体属性名。若未设置,将扫描实体中带有@EmbeddingVector注解的属性。可选
embeddedTextAttributeName表示向量嵌入源文本的实体属性名。若未设置,将扫描实体中带有@EmbeddedText注解的属性。可选
unmappedMetadataAttributeName表示存储未映射元数据的 JSON 列的实体属性名。若未设置,将扫描实体中带有@UnmappedMetadata注解的属性。可选
metadataAttributeNames显式映射为文本元数据的实体属性名集合。若未设置,将扫描实体中带有@MetadataAttribute注解的属性。可选
distanceFunction向量搜索所用距离函数,取值与 Generic Store 相同。COSINE可选(若未设置,扫描@EmbeddingVector注解上的distance取值;若注解上也未配置,则回退到默认COSINE

快速开始:Docker 启动 PostgreSQL + PGVector

文档与源码测试均以 PostgreSQL + PGVector 作为示范数据库(相关集成测试见 PgVectorHibernateEmbeddingStoreIT.java 等)。使用 Testcontainers 与pgvector/pgvector镜像可以快速拉起一个带向量扩展的实例。

用 Docker 启动测试实例

docker run --rm --name langchain4j-postgres-test-container -p 5432:5432 -e POSTGRES_USER=my_user -e POSTGRES_PASSWORD=my_password pgvector/pgvector

命令参数说明:

  • docker run:启动一个新容器。
  • --rm:容器停止后自动移除,确保不残留数据。
  • --name langchain4j-postgres-test-container:为容器命名,便于识别。
  • -p 5432:5432:将本机 5432 端口映射到容器内 5432 端口。
  • -e POSTGRES_USER=my_user:设置 PostgreSQL 用户名为my_user
  • -e POSTGRES_PASSWORD=my_password:设置 PostgreSQL 密码为my_password
  • pgvector/pgvector:指定 Docker 镜像,已预配置 PGVector 扩展。

示例一:仅必填参数的最小配置

HibernateEmbeddingStore embeddingStore = HibernateEmbeddingStore.dynamicBuilder() .databaseKind(DatabaseKind.POSTGRESQL) // Required: The database kind .host("localhost") // Required: Host of the database server .port(5432) // Required: Port of the database server .database("postgres") // Required: Database name .user("my_user") // Required: Database user .password("my_password") // Required: Database password .table("my_embeddings") // Required: Table name to store embeddings .dimension(embeddingModel.dimension()) // Required: Dimension of embeddings .build();

这段配置演示了最核心的七个必填项:数据库类型、连接地址、表名与向量维度。其中dimension建议始终取自embeddingModel.dimension(),确保表结构与嵌入模型严格匹配。

示例二:配置全部常用参数

HibernateEmbeddingStore embeddingStore = HibernateEmbeddingStore.dynamicBuilder() // Required parameters .databaseKind(DatabaseKind.POSTGRESQL) .host("localhost") .port(5432) .database("postgres") .user("my_user") .password("my_password") .table("my_embeddings") .dimension(embeddingModel.dimension()) // Optional parameters .createIndex(true) // Enable vector index creation .indexType("ivfflat") // Index type IVFFlat .indexOptions("lists = 100") // Number of lists for IVFFlat index .createTable(true) // Automatically create the table if it doesn't exist .dropTableFirst(false) // Don't drop the table first (set to true if you want a fresh start) .distanceFunction(DistanceFunction.MANHATTEN) // Use MANHATTAN distance function for vector search .build();

提示:上述示例中的.distanceFunction(DistanceFunction.MANHATTEN)是官方文档中的写法。需要留意的是,仓库源码 DistanceFunction.java 中实际定义的枚举名是MANHATTAN(而非MANHATTEN),编译时请以源码枚举名为准。该枚举同时提供了COSINEEUCLIDEANEUCLIDEAN_SQUAREDINNER_PRODUCTNEGATIVE_INNER_PRODUCTHAMMINGJACCARD等取值。

第一个示例适合快速跑通;第二个示例展示了全部常用可选参数,便于对索引与搜索行为做精细控制。

使用完毕后,记得调用close()关闭HibernateEmbeddingStore,以释放底层 Hibernate 资源。

自定义 Hibernate 实体:用注解声明向量字段

当需要定制数据模型,或希望复用已有实体作为EmbeddingStore的数据源时,可以使用四个注解标记实体属性:

  • @EmbeddingVector:标记表示嵌入向量的持久化属性。默认按 32 位浮点向量(VECTOR_FLOAT32)处理,可通过@JdbcTypeCode(SqlTypes.VECTOR_FLOAT16)等覆盖向量类型(支持VECTOR_BINARYVECTOR_INT8VECTOR_FLOAT16VECTOR_FLOAT32VECTOR_FLOAT64以及稀疏向量类型);注解本身带有distance属性用于声明该字段的向量搜索距离函数。
  • @EmbeddedText:标记生成嵌入向量的源文本属性。
  • @UnmappedMetadata:标记未映射元数据的容器属性,可以是Map<String, Object>String(以 JSON 列存储),全实体最多只能有一个该属性。
  • @MetadataAttribute:标记需要显式映射为文本元数据的属性,负责与TextSegment#metadata的双向同步。

一个最小示例:

@Entity public class MyEmbeddingEntity { @Id UUID id; @EmbeddingVector @Array(length = 384) // The dimension of the embedding vector based on the embedding model float[] embedding; @EmbeddedText String text; @UnmappedMetadata Map<String, Object> metadata; // Can be either a Map<String, Object> or a String @MetadataAttribute String mimeType; // Explicitly mapped. Synchronizes TextSegment#metadata with this attribute @MetadataAttribute String fileName; // Explicitly mapped. Synchronizes TextSegment#metadata with this attribute }

builder 会自动扫描这些注解并推导属性名,因此只需两行核心配置:

HibernateEmbeddingStore embeddingStore = HibernateEmbeddingStore.builder() .sessionFactory(sessionFactory) // Required: The SessionFactory containing your entity class .entityClass(MyEmbeddingEntity.class) // Required: The embedding entity class .build();

如果不想(或无法)在实体上添加注解,也可以显式声明属性名:

HibernateEmbeddingStore embeddingStore = HibernateEmbeddingStore.builder() .sessionFactory(sessionFactory) .entityClass(MyEmbeddingEntity.class) .embeddingAttributeName("embedding") .embeddedTextAttributeName("text") .unmappedMetadataAttributeName("metadata") .metadataAttributeNames("mimeType", "fileName") .build();

嵌套元数据:关联实体的元数据映射与过滤

元数据还可以嵌套在@OneToOne@ManyToOne@Embedded属性中——只要这些属性同时标注@MetadataAttribute,或通过.(点号)分隔符指定显式属性路径。仓库测试中的 BookEntity.java 正是这种模式的真实用例:

@Entity public class Book { @Id private Long id; private String title; private String content; @MetadataAttribute @Embedded private BookDetails details = new BookDetails(); @MetadataAttribute @ManyToOne(fetch = FetchType.LAZY) private Author author; @EmbeddingVector @Array(length = 384) private float[] embedding; @UnmappedMetadata private Map<String, Object> metadata; } @Entity public class Author { @Id @MetadataAttribute @GeneratedValue private Long id; private String firstname; private String lastname; } @Embeddable public class BookDetails { @MetadataAttribute private String language; private String abstractText; }

对应的属性路径为details.languageauthor.id,可直接作为元数据键参与过滤:

MetadataFilterBuilder.metadataKey("details.language").isEqualTo("English")
MetadataFilterBuilder.metadataKey("author.id").isEqualTo(2L)

类型安全的 Hibernate Restriction 搜索

除了基于Metadata的过滤,HibernateEmbeddingStore还提供search重载方法,允许直接使用 Hibernate ORM 类型安全的RestrictionAPI 构建查询条件:

HibernateEmbeddingStore<Book> embeddingStore = embeddingStore(); embeddingStore.search( embedding, Path.from(Book.class) .to(Book_.details) .to(BookDetails_.language) .equalTo("English"));

或:

HibernateEmbeddingStore<Book> embeddingStore = embeddingStore(); embeddingStore.search( embedding, Path.from(Book.class) .to(Book_.author) .to(Author_.id) .equalTo(2L));

这种写法由编译期生成的元模型类(如Book_BookDetails_Author_)保证路径的类型安全,字段名拼写错误会在编译阶段暴露,而非运行时。源码 HibernateEmbeddingStore.java 的实现中同时支持 LangChain4j 标准的FilterIsEqualToIsGreaterThanIsInAnd/Or/Not等逻辑组合)与 HibernateRestriction两种过滤体系,前者的过滤逻辑可在 HibernateEmbeddingStoreContractTest.java 等契约测试中看到覆盖。

完整 RAG 示例:Hibernate + PGVector

本节演示如何用 Hibernate 集成构建一套完整的检索增强生成(RAG)系统。RAG 系统包含两个主要阶段:

  1. 索引阶段(离线):加载文档、切分块、生成嵌入、存入 pgvector。
  2. 检索阶段(在线):对用户查询生成嵌入、检索相似块、将上下文注入 LLM 提示词。

前置条件:确保已按上文 Docker 方式启动带 PGVector 的 PostgreSQL 实例。

阶段一:文档摄入(Indexing)

import dev.langchain4j.data.document.Document; import dev.langchain4j.data.document.DocumentParser; import dev.langchain4j.data.document.DocumentSplitter; import dev.langchain4j.data.document.parser.apache.pdfbox.ApachePdfBoxDocumentParser; import dev.langchain4j.data.document.splitter.DocumentSplitters; import dev.langchain4j.data.embedding.Embedding; import dev.langchain4j.data.segment.TextSegment; import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.embedding.onnx.allminilml6v2.AllMiniLmL6V2EmbeddingModel; import dev.langchain4j.store.embedding.EmbeddingStore; import dev.langchain4j.store.embedding.EmbeddingStoreIngestor; import static dev.langchain4j.data.document.loader.FileSystemDocumentLoader.loadDocument; // Load document (PDF, TXT, etc.) Document document = loadDocument("/path/to/document.pdf", new ApachePdfBoxDocumentParser()); // Split document into smaller chunks // 300 tokens per chunk, 50 tokens overlap for context continuity DocumentSplitter splitter = DocumentSplitters.recursive(300, 50); // Create embedding model (384 dimensions for AllMiniLmL6V2) EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel(); // Create pgvector embedding store HibernateEmbeddingStore embeddingStore = HibernateEmbeddingStore.dynamicBuilder() .databaseKind(DatabaseKind.POSTGRESQL) .host("localhost") .port(5432) .database("postgres") .user("my_user") .password("my_password") .table("document_embeddings") .dimension(embeddingModel.dimension()) // 384 for AllMiniLmL6V2 .build(); // Ingest: split document, generate embeddings, and store in pgvector EmbeddingStoreIngestor.builder() .documentSplitter(splitter) .embeddingModel(embeddingModel) .embeddingStore(embeddingStore) .build() .ingest(document); System.out.println("Document ingested successfully!");

这里的EmbeddingStoreIngestor是 LangChain4j 提供的标准摄入管线:自动完成"切分 → 向量化 → 写入 store"三步,你只需要注入 splitter、embeddingModel 与 embeddingStore。示例中使用的AllMiniLmL6V2EmbeddingModel对应仓库中的 langchain4j-embeddings-all-minilm-l6-v2 模块(测试中亦使用其量化版langchain4j-embeddings-all-minilm-l6-v2-q,见 langchain4j-hibernate/pom.xml),输出 384 维向量。

阶段二:查询检索(Retrieval)

import dev.langchain4j.data.embedding.Embedding; import dev.langchain4j.data.message.AiMessage; import dev.langchain4j.model.chat.ChatModel; import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.store.embedding.EmbeddingMatch; import java.util.List; import java.util.stream.Collectors; // User's question String question = "What is the refund policy?"; // Generate embedding for the question Embedding questionEmbedding = embeddingModel.embed(question).content(); // Search for the most similar text segments (top 3 results) EmbeddingSearchResult<TextSegment> result = embeddingStore.search( EmbeddingSearchRequest.builder() .queryEmbedding(questionEmbedding) .maxResults(3) // Retrieve top 3 most similar chunks .build() ); // Build context from retrieved segments String context = result.matches().stream() .map(match -> match.embedded().text()) .collect(Collectors.joining("\n\n")); // Create prompt with retrieved context String promptWithContext = String.format(""" Answer the question based on the following context. If the context doesn't contain relevant information, say "I don't have enough information to answer." Context: %s Question: %s Answer: """, context, question); // Send to LLM with context ChatModel chatModel = OpenAiChatModel.builder() .apiKey(System.getenv("OPENAI_API_KEY")) .modelName("gpt-4") .build(); String answer = chatModel.generate(promptWithContext); System.out.println("Answer: " + answer);

检索阶段的关键点:先用与索引阶段同一个EmbeddingModel对查询向量化,再调用embeddingStore.search()拿到按相似度排序的前 N 个匹配(EmbeddingMatch中可通过score()观察相似度分值),将匹配块的文本拼接为上下文,最后连同用户问题一起交给大模型生成答案。EmbeddingSearchRequest还支持minScorefilter(元数据过滤)等参数,用于进一步收紧召回结果。

生产环境实践建议

基于真实使用经验,以下是生产部署时的重要考量。

1. 连接池

生产环境应使用带连接池的DataSource,而非零散的单连接参数。这里用 HikariCP 示范(其配置类来自第三方库com.zaxxer.hikari,需自行引入依赖):

import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:postgresql://localhost:5432/postgres"); config.setUsername("my_user"); config.setPassword("my_password"); config.setMaximumPoolSize(10); HikariDataSource dataSource = new HikariDataSource(config); EmbeddingStore<TextSegment> embeddingStore = HibernateEmbeddingStore.dynamicDatasourceBuilder() .databaseKind(DatabaseKind.POSTGRESQL) .datasource(dataSource) .table("document_embeddings") .dimension(384) .build();

注意此处dimension直接写死为 384(对应示例嵌入模型),实际项目中仍推荐用embeddingModel.dimension()动态获取。

2. 索引优化

对于大数据集(超过 10 万条嵌入),建议在 PostgreSQL 上开启 IVFFlat 索引以提升查询性能:

HibernateEmbeddingStore embeddingStore = HibernateEmbeddingStore.dynamicBuilder() // ... other config ... .createIndex(true) .indexOptions("lists = 100") // Adjust based on dataset size .build();
  • 注意:在大数据集上创建索引可能耗时较长,需要在查询速度与索引构建时间之间做权衡。
  • 注意:索引维护会拖慢数据摄入,批量导入大数据量时,可考虑先删索引、导入完成后再重建。

3. 分块大小调优

根据业务场景实验不同分块大小:

  • 较小的块(200~300 tokens):精度更高,答案更聚焦、更具体。
  • 较大的块(500~800 tokens):上下文更丰富,但可能降低相关性。

4. 错误处理

始终优雅地处理数据库连接失败:

try { embeddingStore.add(embedding, textSegment); } catch (Exception e) { logger.error("Failed to store embedding", e); // Implement retry logic or fallback behavior }

5. 自定义实体时的 DDL 管理

使用自定义 Hibernate 实体时,DDL 需要你自行负责。建议创建import.sql来建索引。例如 PostgreSQL:

create index if not exists my_entity_ivfflat_index on my_entity using ivfflat(embedding vector_cosine_ops) with (lists = 1);

关于SessionFactory的详细配置,可参考 Hibernate ORM 官方用户指南(此处不做外部链接展开)。向量索引在其他数据库上的语法与选项各不相同,需查阅对应数据库提供方的文档。

各数据库向量索引 DDL 速查

DatabaseKind源码为每种数据库内置了索引 DDL 生成逻辑(createIndexDDL方法),同时官方文档也给出了手工建索引的参考 SQL,两者可互为印证。下面按数据库汇总:

DB2

create vector index my_entity_vector_index on my_entity(embedding) with distance cosine;

从 DatabaseKind.java 可见,DB2 支持的 distance 值包括cosineeuclideaneuclidean_squaredmanhattanhammingjaccarddot(对应内积类距离函数)。

MariaDB

create vector index if not exists my_entity_vector_index on my_entity(embedding) distance=cosine;

MariaDB 仅支持cosineeuclidean两种距离度量(见 DatabaseKind.java),使用其他距离函数会在运行时抛出IllegalArgumentException

MySQL

MySQL HeatWave 会自动创建索引,无需手工建索引(对应源码中 MySQL 的createIndexDDL直接返回null,见 DatabaseKind.java)。

PostgreSQL

create index if not exists my_entity_ivfflat_index on my_entity using ivfflat(embedding vector_cosine_ops) with (lists = 1);

PostgreSQL 的vectorOps与距离函数映射关系(来自 DatabaseKind.java):COSINE → vector_cosine_opsEUCLIDEAN/EUCLIDEAN_SQUARED → vector_l2_opsMANHATTAN → vector_l1_opsHAMMING → vector_hamming_opsJACCARD → vector_jaccard_opsINNER_PRODUCT/NEGATIVE_INNER_PRODUCT → vector_ip_ops。未指定indexType时默认使用ivfflat,并且会在建索引前执行create extension if not exists vector;的初始化 SQL。

CockroachDB

create vector index if not exists my_entity_ivfflat_index on my_entity (embedding vector_cosine_ops);

CockroachDB 的 JDBC URL 与 PostgreSQL 相同,但建索引语法独立,且初始化时会执行set cluster setting feature.vector_index.enabled = true;(见 DatabaseKind.java),只支持vector_cosine_opsvector_l2_opsvector_ip_ops

Oracle

create vector index my_entity_vector_index on my_entity(embedding) organization neighbor partitions with distance cosine;

Oracle 支持的 distance 值最全(cosineeuclideaneuclidean_squaredmanhattanhammingjaccarddot,见 DatabaseKind.java)。

SQL Server

create vector index my_entity_vector_index on my_entity(embedding) with (metric='cosine');

SQL Server 的 metric 支持'cosine''euclidean''dot'三种取值,JDBC URL 模板中还内置了sendTimeAsDatetime=falsetrustServerCertificate=true等连接参数(见 DatabaseKind.java)。

SAP HANA

create hnsw vector index my_entity_vector_index on my_entity(embedding) with similarity function cosine_similarity;

SAP HANA 使用 HNSW 索引,支持cosine_similarityl2distance两种相似度函数(见 DatabaseKind.java)。

源码原理深挖:索引 DDL 与距离函数的自动生成

理解HibernateEmbeddingStore底层行为,有助于在生产中做出正确配置决策。从源码 DatabaseKind.java 可以看出,每种数据库类型封装了四类信息:

  1. JDBC URL 模板:如 PostgreSQL 的jdbc:postgresql://{host}:{port}/{database}、SQL Server 的jdbc:sqlserver://{host}:{port};databaseName={database};...dynamicBuilder()会据此拼接完整连接串。
  2. 索引 DDL 生成函数createIndexDDL(distanceFunction, indexType, table, embeddingColumn, indexOptions)按距离函数把索引操作符/度量映射为各数据库的建索引语句——这就是createIndex=true时自动建索引的实现基础。
  3. 初始化 SQL:如 PostgreSQL 的create extension if not exists vector;、CockroachDB 的集群设置开关,在建表建索引前自动执行。
  4. 数据库识别逻辑isJdbcUrl()用于从 JDBC URL 推断类型,determineDatabaseKind(Dialect)用于从 Hibernate 方言推断类型。

而距离函数枚举 DistanceFunction.java 统一定义了 8 种语义(COSINE、EUCLIDEAN、EUCLIDEAN_SQUARED、MANHATTAN、INNER_PRODUCT、NEGATIVE_INNER_PRODUCT、HAMMING、JACCARD),再由各数据库的 DDL 生成逻辑做"语义 → 方言"的翻译;不支持某距离函数的数据库会在构建索引或初始化时直接抛出IllegalArgumentException,因此建议在项目早期就锁定所用数据库与距离函数组合。

注解层方面,EmbeddingVector.java、EmbeddedText.java、UnmappedMetadata.java 分别通过@JdbcTypeCode将字段映射为 Hibernate 的VECTORLONG32VARCHAR(长文本)与JSON列类型,这也是"一个实体即可同时承载向量、文本与元数据"的技术基础。仓库中 PgVectorHibernateEmbeddingStoreBookEntityIT.java 等集成测试对嵌套元数据、JSONB 过滤、float16 向量、元数据重置等场景均有覆盖,可作为理解行为边界的参考。

【免费下载链接】langchain4jLangChain4j is an idiomatic, open-source Java library for building LLM-powered applications on the JVM. It offers a unified API over popular LLM providers and vector stores, and makes implementing tool calling (including MCP support), agents and RAG easy. It integrates seamlessly with enterprise Java frameworks like Quarkus and Spring Boot.项目地址: https://gitcode.com/GitHub_Trending/la/langchain4j

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询