RU | EN | DE

1. Datenbankverbindung in Spring Boot

📄 application.yml

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/demo
    username: demo
    password: secret
    driver-class-name: org.postgresql.Driver
  jpa:
    hibernate:
      ddl-auto: update  # create, update, validate, none
      show-sql: true       # SQL in der Konsole anzeigen
    properties:
      hibernate.format_sql: true

2. JPA + Hibernate

Spring Data JPA = eine Abstraktionsschicht über Hibernate. Ermöglicht die Arbeit mit der Datenbank wie mit Objekten.

Entity (Tabelle)

import jakarta.persistence.*;
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable = false)
    private String name;
    private String email;
    // Getter/Setter
}

Repository (DAO-Schicht)

import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
    // automatische Methoden anhand des Methodennamens
    List<User> findByName(String name);
    List<User> findByEmailContaining(String part);
}

Spring generiert die Implementierung basierend auf dem Methodennamen.

Service-Schicht

@Service
@RequiredArgsConstructor
public class UserService {
    private final UserRepository repo;
 
    public User createUser(User u) {
        return repo.save(u);
    }
 
    public List<User> allUsers() {
        return repo.findAll();
    }
}

Controller

@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
public class UserController {
    private final UserService service;
 
    @GetMapping
    public List<User> all() {
        return service.allUsers();
    }
 
    @PostMapping
    public User create(@RequestBody User user) {
        return service.createUser(user);
    }
}

3. JPQL & Native Queries

📌 Wenn der findBy... Methode nicht ausreicht…

public interface UserRepository extends JpaRepository<User, Long> {
    // JPQL (arbeitet mit Entities, nicht mit Tabellen)
    @Query("SELECT u FROM User u WHERE u.name = :name")
    List<User> findByNameJPQL(@Param("name") String name);
    // Native SQL
    @Query(value = "SELECT * FROM users WHERE email LIKE %:email%", nativeQuery = true)
    List<User> findByEmailNative(@Param("email") String email);
}

4. DTO (Data Transfer Object)

Um die Entity nicht direkt zurückzugeben (unsicher für APIs).

public record UserDto(Long id, String name) {}
@Service
@RequiredArgsConstructor
class UserService {
    private final UserRepository repo;
 
    public List<UserDto> allUsers() {
        return repo.findAll().stream()
                   .map(u -> new UserDto(u.getId(), u.getName()))
                   .toList();
    }
}

5. Transaction Management

Spring Data JPA umschließt Methoden save/delete automatisch in Transaktionen, aber man kann manuell verwalten.

@Service
public class BankService {
    @Transactional
    public void transfer(Account a1, Account a2, double sum) {
        a1.withdraw(sum);
        a2.deposit(sum);
        // falls hier eine Ausnahme auftritt → wird der gesamte Methode zurückgerollt
    }
}

📌 Standardmäßig: Rollback für RuntimeException.

6. Beziehungen (Entity relationships)

OneToOne

@Entity
class Profile {
    @Id @GeneratedValue Long id;
    String bio;
    @OneToOne
    User user;
}

OneToMany / ManyToOne

@Entity
class User {
    @Id @GeneratedValue Long id;
    String name;
    @OneToMany(mappedBy = "user")
    List<Post> posts = new ArrayList<>();
}
@Entity
class Post {
    @Id @GeneratedValue Long id;
    String text;
    @ManyToOne
    User user;
}

ManyToMany

@Entity
class Student {
    @Id @GeneratedValue Long id;
    String name;
    @ManyToMany
    @JoinTable(name = "student_course")
    Set<Course> courses;
}
@Entity
class Course {
    @Id @GeneratedValue Long id;
    String title;
    @ManyToMany(mappedBy = "courses")
    Set<Student> students;
}

7. Datenbankmigrationen (Flyway, Liquibase)

Es ist besser, sich nicht auf ddl-auto: update zu verlassen, sondern Migrationen zu verwenden.

Flyway 📄 application.properties

spring.flyway.enabled=true
spring.flyway.locations=classpath:db/migration

📄 src/main/resources/db/migration/V1__init.sql

CREATE TABLE users (
  id BIGSERIAL PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  email VARCHAR(100)
);

Beim Start von Spring Boot werden die Migrationen automatisch angewendet.

8. Paging & Sorting

Spring Data JPA kann automatisch paginieren:

@GetMapping
public Page<User> all(@RequestParam int page, @RequestParam int size) {
    return repo.findAll(PageRequest.of(page, size, Sort.by("name")));
}

📌 Die Antwort ist JSON mit Daten und Metadaten (Seitennummer, Gesamtzahl der Elemente usw.).

9. Best Practices

  • Geben Sie keine Entity im API zurück → Verwenden Sie DTO.
  • ✅ Fügen Sie immer Migrationen (Flyway/Liquibase) hinzu.
  • ✅ Für die Produktion ist ddl-auto=validate besser.
  • ✅ Transaktionen – nur in der Service-Schicht (@Transactional).
  • ✅ Verwenden Sie Pageable für das API → belasten Sie die Datenbank nicht.
  • ✅ Teilen Sie RepositoryServiceController (saubere Architektur).