Object-Relational Mapping (ORM) simplifies database operations in modern applications. This guide will show you how to set up ORM with PostgreSQL using Spring Boot and the Gin framework.
Written by
Şuayb Şimşek
Backend-focused fullstack developer sharing practical notes on Spring Boot, security, microservices, and cloud-native architecture.
Get practical backend + fullstack notes when new articles are published.
Social
🌟 Why Use ORM?
ORM bridges the gap between object-oriented programming and relational databases by mapping objects directly to database tables. This eliminates the need for manual SQL queries, reducing errors and increasing productivity for developers.
📋 Prerequisites
📋 Ensure you have the following:
☕ Java Development Kit (JDK) 17+
📦 Maven or Gradle installed
🖥️ A Java IDE
🐘 PostgreSQL installed and running
For Go:
🔧 Golang 1.17+ installed
🔄 go.mod initialized in your project
🛠️ Step 1: Add Dependencies
To set up a Spring Boot project and integrate ORM, follow these steps:
Add Dependencies
For Spring Boot projects, include the following dependencies in your project:
If you haven't already, create your Spring Boot project using Spring Initializr:
Choose Spring Web, Spring Data JPA, and PostgreSQL Driver as dependencies.
Download the project and import it into your preferred IDE.
For Go projects:
Install Gin Framework and GORM:
BASH
# Install the Gin framework
go get -u github.com/gin-gonic/gin
# Install the GORM PostgreSQL driver
go get -u gorm.io/driver/postgres
# Install the GORM ORM library
go get -u gorm.io/gorm
🛠️ Step 2: Define the Model and Implement the REST Controller
This step combines creating the entity/model, repository, and REST controllers.
▶️ Running the Applications
In this section, we clarify Running the Applications and summarize the key points you will apply in implementation.
Spring Boot:
BASH
./mvnw spring-boot:run
Gin:
BASH
go run main.go
🧪 Testing with cURL
You can test the API using the following cURL commands:
You now have a practical Object-Relational Mapping implementation with a clear, production-friendly Spring Boot structure. As a next step, adapt configuration and tests to your own domain, then validate behavior under realistic traffic and failure scenarios.
Entity
JAVAUser.java
package com.example.demo.entity;
import jakarta.persistence.*;
import lombok.Data;
@Data
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
}
package com.example.demo.controller;
import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/users")
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class UserController {
private final UserRepository userRepository;
@GetMapping
public List<User> getAllUsers() {
return userRepository.findAll();
}
@PostMapping
public User createUser(@RequestBody User user) {
return userRepository.save(user);
}
}
Entity
KOTLINUser.kt
package com.example.demo.entity
import jakarta.persistence.*
@Entity
class User(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long = 0,
var name: String,
var email: String
)
package com.example.demo.controller
import com.example.demo.entity.User
import com.example.demo.repository.UserRepository
import org.springframework.web.bind.annotation.*
@RestController
@RequestMapping("/api/users")
class UserController(
private val userRepository: UserRepository
) {
@GetMapping
fun getAllUsers(): List<User> = userRepository.findAll()
@PostMapping
fun createUser(@RequestBody user: User): User = userRepository.save(user)
}
Model and Database Connection
GOapp.go
package main
import (
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
var DB *gorm.DB
func connectDatabase() {
dsn := "host=localhost user=your_username password=your_password dbname=demo port=5432 sslmode=disable"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic("Failed to connect to database!")
}
DB = db
DB.AutoMigrate(&User{})
}
type User struct {
ID uint `json:"id" gorm:"primaryKey"`
Name string `json:"name"`
Email string `json:"email"`
}
Handlers
GOmain.go
package main
import (
"github.com/gin-gonic/gin"
)
func getUsers(c *gin.Context) {
var users []User
DB.Find(&users)
c.JSON(200, users)
}
func createUser(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
DB.Create(&user)
c.JSON(201, user)
}
func main() {
r := gin.Default()
connectDatabase()
r.GET("/api/users", getUsers)
r.POST("/api/users", createUser)
r.Run() // Listen and serve on 0.0.0.0:8080
}