Note
Full documentation is available at https://uom-demo.vercel.app/docs, including detailed developer guides, architecture overviews, and deployment instructions. Final thesis, with all research, theoretical background, and evaluation results, is available as PDF.
Universal Object Mapping (UOM) is an advanced research and engineering platform designed to automate the translation, validation, and performance optimization of database schemas and query code across diverse Object-Relational Mapping (ORM), Object-Document Mapping (ODM), and Object-Graph Mapping (OGM) paradigms.
Developed within the Adaptive Data Management (ADaM) Research Group at the Department of Software Engineering, Charles University (Faculty of Mathematics and Physics), the project addresses the complex challenges of multi-model database migrations. UOM transitions relational .NET ORM structures (.NET Entity Framework Core, Dapper, NHibernate) into document and graph-based Java Spring Data ecosystems (Spring Data MongoDB, Spring Data Neo4j) with structural compile-and-execute guarantees.
UOM builds directly upon ORMorpher (originally developed by Milan Abrahám as part of his Master's thesis, and later published in the IEEE/ACM International Conference on Automated Software Engineering - ASE 2025).
- Legacy Rule Engine: ORMorpher established C# compiler-based heuristics using the Roslyn Scripting API to map SQL/LINQ queries to an Abstract Representation. It then used Integer Linear Programming (ILP) to dynamically benchmark and select optimal .NET frameworks based on runtime constraints.
- The LLM Advisor Extension: The UOM project extends this foundation by introducing an autonomous LLM Advisor to handle cross-paradigm schema and query transitions (Relational C# to Document/Graph Java). Rather than relying on rigid, hardcoded rules that struggle with heterogeneous schema mapping (like embedding tables vs. document nesting), UOM deploys an iterative, stateful LangGraph translation machine.
The complete UOM system coordinates containerized database engines, schema adapters, a Next.js user interface, and isolated Daytona compilation sandboxes:
graph TD
User([User / Developer]) -->|Interacts| Frontend[Next.js Frontend<br/>uom-translator-ui:3000]
Frontend -->|Queries / Chats| LangGraph[LangGraph Server<br/>langgraph-api:8000]
subgraph Services ["Docker Compose Stack / services"]
Orchestrator[Orchestrator Service<br/>Python Engine] <-->|Drives Graph| LangGraph
Toolbox[GenAI DB Toolbox MCP<br/>db-toolbox:5000] <-->|Schema Inspections| Orchestrator
MongoMCP[MongoDB MCP Server<br/>mongodb-mcp-server:3010] <-->|Mongo Inspections| Orchestrator
MSSQL[(MS SQL Server<br/>mssql_db:1433)] <-->|Relational Source| Toolbox
Mongo[(MongoDB Database<br/>mongodb:27017)] <-->|Target ODM| MongoMCP
Neo4j[(Neo4j Database<br/>neo4j:7687)] <-->|Target OGM| Toolbox
Migrator[MongoDB Relational Migrator<br/>migrator:8080] -->|Relational ETL| Mongo
end
subgraph DaytonaEnv ["Daytona Docker Workspaces"]
Daytona[Daytona Sandbox Daemon] <-->|Restores Environments| Orchestrator
DotnetSandbox[dotnet-10-sandbox] -->|Compiles EFCore/Dapper| MSSQL
JavaSandbox[java-25-sandbox] -->|Compiles Mongo/Neo4j| Mongo
JavaSandbox -->|Compiles Cypher| Neo4j
end
- Frontend User Interface (frontend/uom-translator-ui): A modern Next.js App Router client utilizing assistant-ui library components. Styled with TailwindCSS and Shadcn/UI, it streams compilation diagnostic logs and DeepDiff result comparisons back to the user in real time.
- LLM Orchestrator (services/orchestrator): A Python-based service running a stateful LangGraph execution graph. Details of its state definitions, compiler nodes, and thread parameters are documented in the Orchestrator README.
- Validation Sandboxes: Ephemeral environment containers (.NET 10 SDK and Java OpenJDK 25) managed via Daytona to compile and execute generated code without risk to the host filesystem.
- Relational Source Database: A Microsoft SQL Server instance (
mssql_db) pre-loaded with the WideWorldImporters sample dataset.
To validate query translations against real-world datasets, the target document (MongoDB) and graph (Neo4j) database engines must contain matching, logically equivalent data models. UOM defines a one-time, semi-automatic ETL process to map and migrate relational schemas:
- Relational-to-Document Migration (MongoDB):
- Configured using MongoDB Relational Migrator (web dashboard at
http://localhost:8091). - Users define how SQL columnar tables and primary/foreign key relationships map into MongoDB document collections, specifying document embedding patterns (e.g. embedding order items within parent orders) vs. referencing models.
- The migrator connects via JDBC and executes the ETL pipelines, populating the
uomdatabase in MongoDB.
- Configured using MongoDB Relational Migrator (web dashboard at
- Relational-to-Graph Migration (Neo4j):
- Configured using the Neo4j ETL Tool and APOC plugins OR via the Neo4j ETL CLI for more control and to bypass UI issues. (NOTE: Neo4j ETL Tool UI is only available in Neo4j Desktop v1.6 and older)
- Maps relational tables to graph nodes, and foreign-key joins to node relationship labels (e.g.
(:Order)-[:CONTAINS]->(:Product)). - Populates the graph database, providing equivalent dataset structures prior to Cypher validation.
JDBC connection configurations are mapped inside the services/etl directory.
To run, compile, or debug the monorepo, your host environment must satisfy the following development requirements:
- Docker Environment: Docker Engine 25+ with Docker Compose V2 support (to run relational/NoSQL backends, MCP adapters, and Next.js).
- Python Tooling: Python 3.11+ (better 3.13, cause 3.14+ already causes issues) managed via uv for high-speed workspace synchronization.
- OS: Linux or Windows Subsystem for Linux (WSL) recommended for optimal Docker performance and filesystem compatibility with Daytona sandboxes.
- Node.js Environment: Node.js v24 managed via
pnpmworkspaces (for Next.js App Router). - Daytona Toolchain: Daytona server daemon active locally to manage isolated SDK container sandboxes.
- LLM Providers: Access to high-quality LLMs via Metacentrum e-INFRA CZ OpenAI-compatible vLLM endpoints (e.g. Kimi K2.6, GLM-5), any Open-AI compatible API with a comparable LLM model, or a running local instance of Ollama (e.g. qwen-3.6, qwen3-coder-next).
Follow these step-by-step instructions to boot the complete monorepo stack:
Copy the env templates in the workspace root directory, frontend/uom-translator-ui, and services/orchestrator, and fill in your LLM provider keys, base URLs, and any other necessary parameters:
cp .env.example .env.dev # for development
cp .env.example .env # for production
cp .env.example .env.development # for development in frontend Next.js project
cp .env.example .env.production # for production in frontend Next.js projectBoot the databases, MCP adapters, relational migrator, Daytona stack, and/or Langgraph orchestrator backend in the background:
./scripts/init-project.shEnsure all healthchecks pass. If errors occur, reset with ./scripts/destroy-containers.sh, fix the issues, and try again.
Access the MongoDB Relational Migrator dashboard at http://localhost:8091, connect to the Microsoft SQL Server source, and configure the relational-to-document mapping to migrate the WideWorldImporters dataset into MongoDB. Pre-configured mappings/settings have been prepared in the services/etl/mongodb/UOM WideWorldImporters file for reference (import the project file in UI). For simpler execution, run the provided migration script:
./services/etl/mongodb/run_mongodb_etl.shFor Neo4j, use the Neo4j ETL Tool UI to connect to Microsoft SQL Server and execute the relational-to-graph migration. This approach may result in errors, since Neo4j ETL Tool UI hasn't been updated in a while: in that case, extract the generated mapping file and follow the CLI approach below.
./services/etl/neo4j/run-neo4j-etl.shTo allow the Orchestrator to interact with the Daytona server, an API key must be generated and added to the environment variables.
- Go to http://localhost:3000 to access the Daytona dashboard. You'll be asked to authenticate. Use the default credentials:
- Username:
dev@daytona.io - Password:
password
- Username:
- Once logged in, navigate to the "API Keys" section on the left and create a new API key with "Create Key". Name it
default, and make sure the "Permissions" is set toFull Access. - Copy the generated key and update the
DAYTONA_API_KEYvariable in both.env.devand.envfiles in theservices/orchestratordirectory. - Rebuild the orchestrator service/server after updating the API key.
For more information, see Daytona Docs, specifically the Daytona API Keys section.
Open a separate terminal window, sync the python dependencies, and boot the LangGraph development server:
cd services/orchestrator
direnv allow # if you have direnv installed, otherwise ensure the environment variables are loaded
uv sync --all-extras && ./scripts/load_env.sh && ./scripts/init_daytona_snapshots.sh # or better `make dev` if you have Make (recommended), otherwise check the scripts in Makefile
langgraph dev --allow-blocking # or better `make dev`The server will start listening on http://localhost:2024. The LangSmith Agent Studio web dashboard should be automatically opened.
For development, LLM request mocking is recommended to avoid hitting rate limits and speed up iterations. To enable LLM response mocking, run:
make record_requestsThis will record all LLM requests and responses to a local fixtures directory. Set the .env.dev endpoint accordingly.
Open a third terminal, download the dependencies, and start the Next.js frontend:
cd frontend/uom-translator-ui
pnpm install
pnpm dev:frontendOpen your web browser to http://localhost:3001 (since Daytona API is already running at http://localhost:3000) to access the UOM Assistant UI frontend and begin translating query code!
To deploy the stack in production mode, ensure all environment variables in the .env files are properly configured (domain names, IP addresses, mostly networking-related), and run:
./scripts/init-project-prod.shSee the DevOps & Deployment Operations documentation for detailed information on the production deployment setup, environment variable configurations, and operational guidelines.
- Daytona needs at least 75% of disk space free on host to startup the default runner, i.e. the entire Daytona stack. Very hard to debug.
Part of the benchmarks source code, including some workflows and diagrams, were developed by Milan Abrahám as part of his Master thesis titled Framework-Agnostic Query Adaptation: Ensuring SQL Compatibility Across .NET Database Frameworks. The thesis is available at http://hdl.handle.net/20.500.11956/203083, and the source code is available at https://github.com/milan252525/orm-convertor.
