惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
V
V2EX
大猫的无限游戏
大猫的无限游戏
腾讯CDC
博客园 - Franky
WordPress大学
WordPress大学
Jina AI
Jina AI
GbyAI
GbyAI
云风的 BLOG
云风的 BLOG
B
Blog RSS Feed
Last Week in AI
Last Week in AI
The Cloudflare Blog
V
Visual Studio Blog
P
Proofpoint News Feed
博客园 - 叶小钗
L
LangChain Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Recorded Future
Recorded Future
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
The Blog of Author Tim Ferriss
人人都是产品经理
人人都是产品经理
Y
Y Combinator Blog
罗磊的独立博客
雷峰网
雷峰网
博客园 - 【当耐特】
Microsoft Security Blog
Microsoft Security Blog
L
LINUX DO - 热门话题
Cisco Talos Blog
Cisco Talos Blog
L
Lohrmann on Cybersecurity
Martin Fowler
Martin Fowler
Spread Privacy
Spread Privacy
MongoDB | Blog
MongoDB | Blog
Engineering at Meta
Engineering at Meta
C
Cybersecurity and Infrastructure Security Agency CISA
小众软件
小众软件
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Recent Announcements
Recent Announcements
T
Threat Research - Cisco Blogs
Security Archives - TechRepublic
Security Archives - TechRepublic
量子位
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
宝玉的分享
宝玉的分享
D
DataBreaches.Net
T
The Exploit Database - CXSecurity.com
Vercel News
Vercel News
IT之家
IT之家
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
T
Troy Hunt's Blog
aimingoo的专栏
aimingoo的专栏

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
SQL-First Paradigm: Rethinking Persistence Layer Design from First Principles
Z. Gao · 2026-06-20 · via DEV Community

Foreword

In the Java backend world, ORM (JPA/Hibernate) and MyBatis have long been the default choices for data persistence. But after years of real‑world development, many engineers eventually run into a recurring tension:

There is a fundamental semantic gap between general‑purpose programming languages (3GL) and SQL (4GL).

Attempting to force‑fit SQL into object‑oriented abstractions — or burying SQL under layers of XML tags — often leads to redundant code, limited expressiveness, and painful debugging.

This article explores the SQL‑First persistence paradigm from first principles. We’ll examine the 3GL vs. 4GL distinction, the inherent trade‑offs in ORM and MyBatis, and how a lightweight approach — using simple-dao as a concrete example — can streamline complex queries while keeping SQL fully transparent.

GitHub Repositories

  1. Core Framework: https://github.com/gzz2017gzz/simple-dao
  2. System Base Starter: https://github.com/gzz2017gzz/simple-dao-starter
  3. Code Generator: https://github.com/gzz2017gzz/simple-dao-coder
  4. Production Demo Project: https://github.com/gzz2017gzz/simple-dao-demo

1. The Root Cause: 3GL vs. 4GL — Two Different Universes

1.1 Two Worlds, Two Mathematical Foundations

Modern software development deals with two fundamentally different language families:

Aspect 3GL (General‑Purpose Languages) 4GL (SQL)
Representatives Java, C#, Go, Python, C++ SQL (relational database language)
Mathematical Basis Graph Theory Set Theory + Predicate Logic
Paradigm Imperative / Object‑Oriented Declarative
Core Elements Objects, references, methods, inheritance, polymorphism Tables, rows, columns, keys, relationships
Mental Model Tells the computer “how” to do something Tells the database “what” to retrieve
Abstraction Level Algorithms + data structures in memory Set operations on disk‑resident structured data

1.2 The Semantic Gap Is Inherent

There is no perfect one‑to‑one mapping between 3GL object models and 4GL relational models — this is not a framework limitation, but a mathematical reality:

  • Object inheritance and polymorphism have no direct relational counterpart.
  • Navigating object references (e.g., user.getOrderList()) is not the same as a database JOIN — performance models are completely different.
  • In‑memory object identity (reference address) ≠ database primary key constraints.

Any framework that tries to fully bridge these worlds will inevitably introduce abstraction leaks, performance surprises, and steep learning curves. The question is not whether the gap exists, but how we choose to manage it.


2. Why SQL and Relational Databases Are Still Relevant

2.1 Relational Databases Remain the Backbone of Enterprise Data

Many modern database types — key‑value stores, time‑series databases, vector databases, graph databases — are essentially specialised variations of the relational model:

  • KV stores are single‑table relational tables with just key and value.
  • Time‑series and vector databases add specific indexes and storage optimisations on top of relational structures.
  • Graph databases can be fully represented using node and edge tables.

For core business domains (users, orders, permissions, campus management, ERP), the relational database remains the primary source of truth. Middleware like Redis, Elasticsearch, and ClickHouse serve as supplementary layers — not replacements.

2.2 SQL: A Universal, Cross‑Language Data Language

  • Strong standardisation: Core SQL syntax has been stable for decades, with only minor dialect variations.
  • Full expressiveness: From simple CRUD to complex joins, subqueries, grouping, aggregation, and window functions — SQL handles it all natively.
  • Universal compatibility: Every mainstream language provides a standard SQL interface — Java/Spring JDBC, Python/DB‑API, C#/Dapper, Go/sqlx, Rust/sqlx, etc.

SQL isn’t going away, and neither are relational databases. A persistence design that embraces SQL natively will remain relevant for the foreseeable future.


3. Mainstream Frameworks: A Balanced Look at Their Trade‑offs

3.1 ORM (JPA/Hibernate): A Noble but Imperfect Abstraction

The ORM promise — map relational data to object models — sounds elegant. But given the 3GL/4GL gap, it inevitably introduces challenges:

  • Semantic distortion: Database set operations get translated into object navigation, forcing developers to mentally switch between OOP and relational thinking.
  • SQL opacity: Auto‑generated SQL can be inefficient, hard to tune, and unpredictable under complex joins.
  • N+1 query problem: Object traversal frequently triggers multiple database round‑trips, becoming a performance bottleneck in high‑traffic scenarios.
  • Double learning curve: Developers must master not only Java/OOP but also HQL/JPQL, caching strategies, lazy loading pitfalls, and framework‑specific “gotchas.”

ORM works well for very simple CRUD, but becomes a liability as soon as you need complex joins, aggregations, or reports.

3.2 MyBatis: A Mapping Tool That Gained Too Much Baggage

MyBatis is often called a “semi‑ORM,” but its core job is straightforward: parameter binding + result set mapping. It does not generate SQL or manage object relationships.

To achieve this, however, it has accumulated significant complexity over time:

  • Dual‑file overhead: Mapper interfaces + XML/annotations, leading to fragmented code.
  • Dynamic tag hell: <if>, <where>, <foreach>, OGNL expressions turn dynamic SQL into a puzzle.
  • Complex interceptor system: Custom extensions are hard to write and maintain; most teams rely on community plugins, which can break across upgrades.

Compare this with Spring JDBC, where a single RowMapper does the mapping job in one line. Much of MyBatis’s additional surface area is overhead, not necessity.

Why Did MyBatis Become So Popular?

  • Historical momentum: Early Hibernate was over‑opinionated and restricted native SQL access; MyBatis offered a middle ground.
  • Bandwagon effect: Widespread adoption made it the “safe” choice in many organisations.
  • Misplaced separation myth: The idea that “SQL should be separated from code” became dogma, even though it often just adds indirection.

4. The SQL‑First Paradigm: Design Principles and Architecture

4.1 Core Insight: Dynamic SQL Has a Gradient

A standard SQL statement can be broken into clauses — and not all clauses change at the same frequency:

Clause Dynamism Typical Behaviour
SELECT / FROM / JOIN / GROUP BY Low Table structures and relationships are stable.
HAVING / ORDER BY Medium Occasionally adjusted for new reporting needs.
WHERE / LIMIT High Business filters and pagination change constantly.

This observation drives the SQL‑First strategy:

  1. Stable parts (SELECT, FROM, JOIN, GROUP BY) → Hand‑written SQL, with no framework‑imposed abstraction.
  2. High‑dynamism parts (WHERE, pagination, sorting) → Encapsulated in a 3GL (Java) condition layer, enabling reusability, type safety, and easy debugging.

The goal is not to translate between 3GL and 4GL, but to let each excel in its domain: SQL stays SQL, Java stays Java, with a thin bridge between them.

4.2 Two Golden Rules of SQL‑First Design

These are non‑negotiable boundaries that distinguish SQL‑First from ORM/MyBatis:

  1. No wrapping of SQL keywords or native syntax

    The framework does not provide its own DSL like eq() or like(). Developers write standard SQL fragments directly (AND field = ?).

    → Zero learning curve, full compatibility with all database‑specific features, and zero migration cost if you switch frameworks.

  2. No shielding of database capabilities or native exceptions

    Stored procedures, DDL, streaming queries, vendor‑specific functions all work out‑of‑the‑box. SQL exceptions are propagated directly, not wrapped in framework‑specific errors.

    → Full power of the database, and intuitive debugging.

4.3 A Three‑Layer Architecture (Implemented in simple-dao)

The SQL‑First paradigm naturally decomposes into three distinct layers, each with a clear responsibility:

Layer 1: Condition Layer (BaseCondition) — for High‑Dynamism Clauses

Purpose: Centralised management of WHERE conditions, pagination, and sorting. This is the heart of the paradigm.

  • Features:

    • Provides semantic methods: and(), in(), like(), conditional add().
    • Automatically collects parameter values for SQL placeholders — no manual parameter list maintenance.
    • All conditions converge in a single addCondition() method, ensuring consistent coding standards across the team.
  • Value:

    • Eliminates the single‑table vs. join‑table mental split: Whether it’s a simple CRUD or a 15‑table report, the same condition API is used.
    • Adding or removing a filter is a one‑line change.
    • Supports condition splitting and parameter merging (mergeParams) for complex, modularised business queries.

Layer 2: Execution Layer (BaseSql) — the Bridge

Purpose: A pure execution channel that takes static SQL + dynamic conditions + parameters and executes them via Spring JDBC.

  • Does not parse or modify SQL — fully respects the two golden rules.
  • Provides cross‑dialect pagination, SQL logging with parameter substitution, and other convenience utilities.
  • Fully leverages Spring’s transaction and connection pool management — no re‑invention.

Layer 3: Single‑Table Helper Layer (BaseDao) — for Stable Scenarios

Purpose: Automates single‑table CRUD by resolving entity metadata via annotations at startup (one‑time reflection).

  • Capabilities: Automatic primary key generation, audit field population (creator/creation time), and global logical delete.
  • Implementation: Reuses BaseCondition and BaseSql — no duplicate logic.
  • Outcome: Zero SQL to write for standard single‑table operations, matching ORM convenience where it actually makes sense.

4.4 From Manual String Concatenation to Semantic Units

Traditional JDBC or MyBatis often rely on manual string concatenation or XML tags — error‑prone and verbose.

SQL‑First introduces semantic condition methods that turn each filter into a clear, self‑contained unit:

  • and(fieldSql, value) → generic equality condition, auto‑prepends AND and adds a placeholder.
  • and(fieldSql, value, matchMode) → built‑in prefix/suffix/full wildcard support — no manual % concatenation.
  • in(fieldSql, array) → auto‑expands to IN (?, ?, ?) and handles array parameters.
  • add(sqlFragment, booleanFlag) → conditionally includes a SQL snippet based on a business rule.

Contrast:

Traditional Approach SQL‑First Approach
Multiple if checks scattered across code Single add() line per condition
Manual parameter list management Automatic parameter collection
String concatenation with risk of syntax errors Semantic, IDE‑friendly method calls

5. Practical Engineering Considerations

5.1 Where to Keep SQL Strings: Constants vs. Inline

Based on the dynamic gradient, we recommend:

  • Static SQL (fixed joins, stable table structures) → static final constants.

    Improves readability and reusability. Performance difference is negligible — JVM string optimisations + JDBC prepared statements + database plan caching make it a non‑issue.

  • Dynamic SQL (branching, conditional assembly) → written directly inside the DAO method, using plain Java logic.

    Java’s imperative capabilities are far more expressive than XML tags or OGNL, making complex dynamic logic much more maintainable.

5.2 Code Volume: Why It’s About 1/3 to 1/4 of Traditional Frameworks

The SQL‑First architecture eliminates three broad categories of boilerplate:

  1. MyBatis’s fragmented XML files, endless dynamic tags, and OGNL expressions.
  2. ORM’s massive annotation lists, chainable DSLs, and relationship configuration.
  3. Repeated null‑checks and parameter‑assembly logic across multiple query methods.

The reduction is not about cutting business logic — it’s about removing accidental complexity imposed by the framework.

5.3 Startup and Runtime Performance

  • Reflection is used only once at application startup to resolve entity metadata. At runtime, there is zero reflection overhead — performance is effectively identical to Spring JDBC.
  • Bean scope: BaseDao is prototype‑scoped to isolate metadata per entity type — a deliberate design choice with no performance penalty.
  • Batch handling: the framework provides basic batch capabilities; for extremely large datasets, applications should implement their own batching strategies (which is standard practice across all persistence tools).

5.4 Extension: Leveraging Spring’s Native Ecosystem

Instead of a custom plugin system, SQL‑First frameworks embrace Spring AOP for cross‑cutting concerns:

  • Data permissions
  • Field masking / desensitisation
  • SQL audit logging
  • Multi‑tenancy

This means:

  • Extensions are written in plain Java + Spring, with no framework‑specific learning curve.
  • Caching, read/write splitting, multi‑datasource, and distributed transaction support all come from Spring and middleware — maintaining clear responsibility boundaries.

6. Beyond Java: A Cross‑Language Paradigm

SQL is language‑agnostic, and the SQL‑First paradigm has been successfully implemented across 8 mainstream backend languages:

Language Underlying Driver Implementation Form
Java Spring JDBC simple‑dao and similar frameworks
C# Dapper Condition + Dao layered pattern
Go / Rust sqlx Semantic condition assembly + native SQL
Python SQLAlchemy Core Condition‑based semantic units
PHP / Node.js / C++ Native DB drivers Same layering philosophy

All cross‑language implementations follow the same core rules:

  1. Condition‑layer methods are semantically consistent across languages.
  2. SQL remains fully transparent; native exceptions are passed through.
  3. Single‑table CRUD is automated; complex SQL is hand‑written.

This demonstrates that SQL‑First is not a single framework, but a reusable software engineering pattern that transcends language boundaries.


7. When to Choose SQL‑First (and When Not To)

7.1 Where It Excels

  • Enterprise applications with heavy multi‑table joins, aggregations, and reporting requirements (e.g., ERP, campus management, government systems, microservices).
  • Teams that value uniform coding standards, low maintenance overhead, and want to avoid XML/DSL sprawl.
  • Long‑lived, multi‑developer projects where SQL expertise is already present and DBA involvement is frequent.
  • Projects already in the Spring ecosystem that prefer minimal third‑party plugin dependencies.

7.2 Comparative Summary

Approach Strengths Weaknesses
ORM (JPA/Hibernate) Quick for simple CRUD; automatic schema generation Semantic mismatch; opaque SQL; N+1 problems; steep learning curve for complex queries
MyBatis Full SQL control; widely known XML/annotation fragmentation; dynamic tag complexity; steep extension barrier
Plain Spring JDBC Maximum control; minimal abstraction Excessive boilerplate for conditions; manual parameter management
SQL‑First (e.g., simple‑dao) Native SQL power + condition automation; single‑table CRUD; Spring‑native Requires developers to be comfortable writing SQL (which, for backend engineers, should be a core skill)

8. Final Thoughts: Back to the Essence of Persistence Design

  1. Acknowledge the gap: 3GL and 4GL are different worlds. Full ORM is an over‑ambitious abstraction; MyBatis adds too much accidental complexity for what it actually does.
  2. Respect both languages: Let SQL handle set operations natively. Let Java handle dynamic logic with its full expressive power. Build a thin bridge, not a wall.
  3. Keep it simple: A three‑layer architecture with semantic condition units unifies single‑table and multi‑table queries, eliminates duplication, and enforces consistency.

The best persistence framework is the one you barely notice while writing business logic.

Let SQL be SQL. Let Java be Java. Let the bridge be minimal and transparent.

That is the ultimate goal of the SQL‑First paradigm.


Final Notes

This article was adapted from internal design discussions and production experience across multiple enterprise projects over several years. The simple-dao family of repositories (links at the top) provides a working implementation of these ideas in Java.

If you’ve encountered similar pain points with ORM or MyBatis, or if you’re simply curious about alternative persistence models, we’d love to hear your feedback. Open an issue, start a discussion, or explore the demos — contributions and ideas are always welcome.


License: Apache 2.0

Originally published: 2026-06-20