Skip to main content

Milvus JDBC: Vector Writes and Search

If your application already uses Java and JDBC, can it keep passing parameters through PreparedStatement and reading results through ResultSet when it adds Milvus?

jdbc-milvus provides that entry point. This command finds the two closest vectors within an article category:

SELECT id, title, score FROM blog_jdbc_articles
WHERE category = ?
ORDER BY embedding <-> ? LIMIT 2;

The first parameter is the category; the second is a vector. You still need to understand vector search, but you can keep a familiar Java calling style.

One Mapper: Builders, Annotations, XML

You do not have to choose between writing every query with a builder and putting every query in XML.

An order list can use property-based conditions, a detail lookup needs only one line of SQL, and a report benefits from a separately maintained statement. dbVisitor lets all three live behind the same Mapper interface.

Redis Product Caching with a Mapper

Redis has no relational tables, so what does a Mapper mean here? It means reusing Java interfaces, parameter binding and result mapping—not turning Redis into a SQL database.

A product cache can expose just save, load and evict. Underneath, those methods still execute Redis SET, GET and DEL.

Milvus Entity Mapping and DAO Design

Once the first vector query works, applications usually need stable business operations: add an article, search within a category, or rename a title. Having every caller process ResultSet is not the only option.

This article adds dbVisitor on top of jdbc-milvus: map the collection to an entity, then organize operations behind a Mapper interface.

Milvus with SQL: Queries, ORM and Tools

Java applications typically use the Milvus SDK to write data and search vectors. For relational database developers, SQL and JDBC are more familiar. jdbc-milvus brings that workflow to Milvus:

SELECT id, title, score FROM intro_articles -- score is squared L2 distance; smaller is closer
WHERE category = 'java' -- Search only within the Java category
ORDER BY embedding <-> [1,0] LIMIT 2; -- Return the two nearest vectors

Add dbVisitor to express the same search with entity mapping and a query builder:

@Table("intro_articles")
public class Article {
@Column(primary = true)
private Long id;
private String title;
private String category;
private List<Float> embedding;
// Standard getters and setters omitted
}
LambdaTemplate lambda = new LambdaTemplate(conn);
List<Article> articles = lambda.query(Article.class)
.eq(Article::getCategory, "java")
.orderByL2(Article::getEmbedding, List.of(1F, 0F))
.initPage(2, 0)
.queryForList();

Mapping BCE Dates: Two Approaches

BCE dates cause subtle "off-by-one" bugs between Java and databases. dbVisitor 6.7.0 adds JulianDayTypeHandler and PgDateTypeHandler to provide cross-database and PostgreSQL-native mappings. Database date ranges and handler boundaries still need consideration.