Skip to content

ORM Compatibility

ParticleDB implements the PostgreSQL wire protocol, so most ORMs and query builders that support PostgreSQL work with no changes. Point the connection string at ParticleDB and go.

ORM / FrameworkLanguageConnection StringStatus
SQLAlchemyPythonpostgresql://localhost:5432/mainTested
Django ORMPythonSee belowTested
PrismaTypeScriptpostgresql://localhost:5432/mainTested
Drizzle ORMTypeScriptpostgresql://localhost:5432/mainTested
TypeORMTypeScriptpostgresql://localhost:5432/mainTested
GORMGohost=localhost port=5432 dbname=mainTested
DieselRustpostgresql://localhost:5432/mainTested
Hibernate / JPAJavajdbc:postgresql://localhost:5432/mainTested
JOOQJavajdbc:postgresql://localhost:5432/mainTested
Entity Framework CoreC# / .NETHost=localhost;Port=5432;Database=mainTested
DapperC# / .NETHost=localhost;Port=5432;Database=mainTested
Terminal window
pip install sqlalchemy psycopg2-binary
from sqlalchemy import create_engine, Column, BigInteger, String, Float
from sqlalchemy.orm import declarative_base, Session
engine = create_engine("postgresql://localhost:5432/main")
Base = declarative_base()
class Product(Base):
__tablename__ = "products"
id = Column(BigInteger, primary_key=True)
name = Column(String, nullable=False)
price = Column(Float)
# Create tables
Base.metadata.create_all(engine)
# Insert
with Session(engine) as session:
session.add(Product(id=1, name="Wireless Mouse", price=29.99))
session.commit()
# Query
with Session(engine) as session:
products = session.query(Product).filter(Product.price > 20).all()
for p in products:
print(f"{p.name}: ${p.price:.2f}")
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
# Use asyncpg as the async driver
engine = create_async_engine("postgresql+asyncpg://localhost:5432/main")
async with AsyncSession(engine) as session:
result = await session.execute(select(Product).where(Product.price > 20))
for p in result.scalars():
print(f"{p.name}: ${p.price:.2f}")

In settings.py:

DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "main",
"HOST": "localhost",
"PORT": "5432",
}
}
models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=255)
price = models.FloatField()
class Meta:
db_table = "products"
# Usage
Product.objects.create(name="Wireless Mouse", price=29.99)
expensive = Product.objects.filter(price__gt=50).order_by("-price")

In schema.prisma:

datasource db {
provider = "postgresql"
url = "postgresql://localhost:5432/main"
}
generator client {
provider = "prisma-client-js"
}
model Product {
id BigInt @id
name String
price Float?
}
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
// Insert
await prisma.product.create({
data: { id: 1n, name: "Wireless Mouse", price: 29.99 },
});
// Query
const expensive = await prisma.product.findMany({
where: { price: { gt: 50 } },
orderBy: { price: "desc" },
});
console.log(expensive);
Terminal window
npm install drizzle-orm pg
npm install -D drizzle-kit @types/pg
import { drizzle } from "drizzle-orm/node-postgres";
import { pgTable, bigint, varchar, doublePrecision } from "drizzle-orm/pg-core";
import { gt } from "drizzle-orm";
import { Client } from "pg";
const products = pgTable("products", {
id: bigint("id", { mode: "number" }).primaryKey(),
name: varchar("name").notNull(),
price: doublePrecision("price"),
});
const client = new Client("postgresql://localhost:5432/main");
await client.connect();
const db = drizzle(client);
// Insert
await db.insert(products).values({ id: 1, name: "Wireless Mouse", price: 29.99 });
// Query
const expensive = await db.select().from(products).where(gt(products.price, 50));
console.log(expensive);
Terminal window
npm install typeorm pg reflect-metadata
import { DataSource, Entity, PrimaryColumn, Column } from "typeorm";
import "reflect-metadata";
@Entity("products")
class Product {
@PrimaryColumn("bigint")
id: number;
@Column("varchar")
name: string;
@Column("double precision", { nullable: true })
price: number;
}
const ds = new DataSource({
type: "postgres",
host: "localhost",
port: 5432,
database: "main",
entities: [Product],
synchronize: true,
});
await ds.initialize();
const repo = ds.getRepository(Product);
// Insert
await repo.save({ id: 1, name: "Wireless Mouse", price: 29.99 });
// Query
const expensive = await repo.find({
where: { price: MoreThan(50) },
order: { price: "DESC" },
});
Terminal window
go get gorm.io/gorm
go get gorm.io/driver/postgres
package main
import (
"fmt"
"log"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type Product struct {
ID int64 `gorm:"primaryKey"`
Name string `gorm:"not null"`
Price float64
}
func main() {
dsn := "host=localhost port=5432 dbname=main sslmode=disable"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
// Auto-migrate
db.AutoMigrate(&Product{})
// Insert
db.Create(&Product{ID: 1, Name: "Wireless Mouse", Price: 29.99})
// Query
var products []Product
db.Where("price > ?", 50).Order("price desc").Find(&products)
for _, p := range products {
fmt.Printf("%s: $%.2f\n", p.Name, p.Price)
}
}
Terminal window
cargo add diesel --features postgres
cargo install diesel_cli --no-default-features --features postgres
// schema.rs (generated by diesel CLI)
diesel::table! {
products (id) {
id -> Int8,
name -> Varchar,
price -> Nullable<Float8>,
}
}
// models.rs
use diesel::prelude::*;
#[derive(Queryable, Selectable)]
#[diesel(table_name = products)]
struct Product {
id: i64,
name: String,
price: Option<f64>,
}
#[derive(Insertable)]
#[diesel(table_name = products)]
struct NewProduct<'a> {
id: i64,
name: &'a str,
price: Option<f64>,
}
// main.rs
use diesel::prelude::*;
use diesel::pg::PgConnection;
fn main() {
let database_url = "postgresql://localhost:5432/main";
let mut conn = PgConnection::establish(database_url)
.expect("Error connecting to ParticleDB");
// Insert
diesel::insert_into(products::table)
.values(&NewProduct { id: 1, name: "Wireless Mouse", price: Some(29.99) })
.execute(&mut conn)
.expect("Error inserting");
// Query
let results = products::table
.filter(products::price.gt(50.0))
.order(products::price.desc())
.load::<Product>(&mut conn)
.expect("Error querying");
for p in results {
println!("{}: ${:.2}", p.name, p.price.unwrap_or(0.0));
}
}

The DATABASE_URL for Diesel CLI:

Terminal window
echo "DATABASE_URL=postgresql://localhost:5432/main" > .env
diesel setup
diesel migration generate create_products

In persistence.xml:

<persistence-unit name="particledb">
<properties>
<property name="jakarta.persistence.jdbc.url"
value="jdbc:postgresql://localhost:5432/main"/>
<property name="jakarta.persistence.jdbc.driver"
value="org.postgresql.Driver"/>
<property name="hibernate.dialect"
value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
@Entity
@Table(name = "products")
public class Product {
@Id
private Long id;
private String name;
private Double price;
// getters, setters
}
// Usage
EntityManagerFactory emf = Persistence.createEntityManagerFactory("particledb");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(new Product(1L, "Wireless Mouse", 29.99));
em.getTransaction().commit();
List<Product> expensive = em.createQuery(
"SELECT p FROM Product p WHERE p.price > :price ORDER BY p.price DESC",
Product.class
).setParameter("price", 50.0).getResultList();
Terminal window
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
using Microsoft.EntityFrameworkCore;
public class AppDbContext : DbContext
{
public DbSet<Product> Products => Set<Product>();
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseNpgsql("Host=localhost;Port=5432;Database=main");
}
}
public class Product
{
public long Id { get; set; }
public string Name { get; set; } = "";
public double? Price { get; set; }
}
// Usage
await using var db = new AppDbContext();
// Insert
db.Products.Add(new Product { Id = 1, Name = "Wireless Mouse", Price = 29.99 });
await db.SaveChangesAsync();
// Query
var expensive = await db.Products
.Where(p => p.Price > 50)
.OrderByDescending(p => p.Price)
.ToListAsync();
foreach (var p in expensive)
{
Console.WriteLine($"{p.Name}: ${p.Price:F2}");
}

All ORMs use standard PostgreSQL connection strings. Here is the format for each:

ORMFormatExample
SQLAlchemypostgresql://host:port/dbpostgresql://localhost:5432/main
DjangoDict in settings.pySee Django section above
Prismapostgresql://host:port/dbpostgresql://localhost:5432/main
Drizzlepostgresql://host:port/dbpostgresql://localhost:5432/main
TypeORMSeparate fields or URLhost: "localhost", port: 5432
GORMDSN stringhost=localhost port=5432 dbname=main
Dieselpostgresql://host:port/dbpostgresql://localhost:5432/main
HibernateJDBC URLjdbc:postgresql://localhost:5432/main
EF CoreNpgsql stringHost=localhost;Port=5432;Database=main

Most PostgreSQL ORMs work seamlessly. A few features that rely on PostgreSQL-specific internals may have limited support:

  • Schema migrations that use pg_catalog introspection queries may need adjustments
  • Advisory locks used by some migration tools are not yet supported
  • Sequences (auto-increment) work via BIGINT PRIMARY KEY with application-generated IDs
  • ENUM types are not yet supported; use VARCHAR with application-level validation

If you encounter compatibility issues with a specific ORM, please report them — we continually expand protocol coverage.