Migration Deep Dive für 04 · Persistenz öffnen →
⌂ ÜbersichtAlle Vergleiche
Modul 04 · 100 % Codeabdeckung

Persistenz

Vollständiger Legacy-Modern-Vergleich aller Java-Klassen, Tests, Maven-POMs und relevanten Ressourcen dieses Moduls. Jede Datei ist genau einmal einer fachlich passenden Vergleichsgruppe zugeordnet.

6Legacy-Dateien
7Modern-Dateien
151 → 158Codezeilen
14/14vollständig erfasst

Fachliche Einordnung

Legacy

DAO mit handgeschriebenem JDBC

SQL, Connection-Handling, Schemaerzeugung und Mapping liegen in einer konkreten DAO-Klasse.

Modern

Spring Data JPA Repository

Spring Data erzeugt die Repository-Implementierung; eine Service Layer bildet die Transaktionsgrenze.

Vergleichsfokus: Alle Dateien werden nach technischer Rolle und fachlicher Verantwortung gruppiert.
Wichtige Abgrenzung: One-to-many-Änderungen werden als Gruppe dargestellt; eine künstliche 1:1-Zuordnung wird vermieden.

Vollständige Abdeckungsmatrix

Die Ähnlichkeit ist eine technische Orientierung auf normalisiertem Quelltext. Sie ersetzt keine fachliche Bewertung.

VergleichsgruppeLegacy-DateienModern-DateienLegacy-ZeilenModern-ZeilenÄhnlichkeit
Build-Konfiguration11354356%
Bootstrap und Datenbankkonfiguration12122412%
Domänen-/Persistenzmodell114416%
Datenzugriff und Test32100255%
Service Layer010250%

Gemeinsame Modulstruktur

Das Pair-POM bindet die Legacy- und Modern-Submodule zusammen und gehört deshalb ebenfalls zur vollständigen Codeabdeckung.

Gemeinsam · 19 Zeilenpom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>at.aydin.academy</groupId>
        <artifactId>java-modernization-deep-dive</artifactId>
        <version>1.0.0</version>
        <relativePath>../../pom.xml</relativePath>
    </parent>
    <artifactId>04persistence-pair</artifactId>
    <packaging>pom</packaging>
    <name>Persistenz: Legacy und Modern</name>
    <modules>
        <module>legacy</module>
        <module>modern</module>
    </modules>
</project>

Alle semantischen Codevergleiche

01Build-KonfigurationDirektvergleich · Legacy 35 / Modern 43 Zeilen · Ähnlichkeit 56%

JDBC-/JPA- und Testabhängigkeiten werden verglichen.

Legacy-DateienModern-DateienEinordnung
pom.xmlpom.xmlDirektvergleich
Semantische Ähnlichkeit: 56%

Legacy

Legacy · 35 Zeilenlegacy/pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>at.aydin.academy</groupId>
        <artifactId>04persistence-pair</artifactId>
        <version>1.0.0</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <artifactId>persistence-legacy</artifactId>
    <packaging>jar</packaging>
    <name>Persistence Legacy (JDBC)</name>
    <dependencies>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
            </plugin>

        </plugins>
    </build>
</project>

Modern

Modern · 43 Zeilenmodern/pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>at.aydin.academy</groupId>
        <artifactId>04persistence-pair</artifactId>
        <version>1.0.0</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <artifactId>persistence-modern</artifactId>
    <packaging>jar</packaging>
    <name>Persistence Modern (Spring Data JPA)</name>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
02Bootstrap und DatenbankkonfigurationDirektvergleich · Legacy 12 / Modern 24 Zeilen · Ähnlichkeit 12%

Manuelles Setup wird durch Spring Boot und Properties ersetzt.

Legacy-DateienModern-DateienEinordnung
PersistenceLegacyApplication.javaPersistenceModernApplication.java
application.properties
Direktvergleich
Semantische Ähnlichkeit: 12%

Legacy

package at.aydin.lab.persistence.legacy;

public final class PersistenceLegacyApplication {
    private PersistenceLegacyApplication() {
    }

    public static void main(String[] args) {
        CustomerDao dao = new JdbcCustomerDao("jdbc:h2:mem:legacy;DB_CLOSE_DELAY=-1");
        dao.save("Aydin Polat", "aydin@example.test");
        dao.findAll().forEach(System.out::println);
    }
}

Modern

package at.aydin.lab.persistence.modern;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class PersistenceModernApplication {
    public static void main(String[] args) {
        SpringApplication.run(PersistenceModernApplication.class, args);
    }

    @Bean
    CommandLineRunner demo(CustomerService service) {
        return args -> {
            service.create("Aydin Polat", "aydin@example.test");
            service.findAll().forEach(System.out::println);
        };
    }
}
03Domänen-/PersistenzmodellDirektvergleich · Legacy 4 / Modern 41 Zeilen · Ähnlichkeit 6%

POJO und persistierbare Entity werden verglichen.

Legacy-DateienModern-DateienEinordnung
Customer.javaCustomerEntity.javaDirektvergleich
Semantische Ähnlichkeit: 6%

Legacy

Modern

package at.aydin.lab.persistence.modern;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Entity
@Table(name = "customer")
public class CustomerEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;
    protected CustomerEntity() {
    }

    public CustomerEntity(String name, String email) {
        this.name = name;
        this.email = email;
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getEmail() {
        return email;
    }

    @Override
    public String toString() {
        return "CustomerEntity[id=" + id + ", name=" + name + ", email=" + email + "]";
    }
}
04Datenzugriff und TestDirektvergleich · Legacy 100 / Modern 25 Zeilen · Ähnlichkeit 5%

DAO-Interface plus JDBC-Implementierung wird durch Spring Data Repository ersetzt.

Legacy-DateienModern-DateienEinordnung
CustomerDao.java
JdbcCustomerDao.java
JdbcCustomerDaoTest.java
CustomerRepository.java
CustomerRepositoryTest.java
Direktvergleich
Semantische Ähnlichkeit: 5%

Legacy

package at.aydin.lab.persistence.legacy;

import java.util.List;

// Design Pattern: DAO
// Zweck: SQL und JDBC werden hinter einer fachlichen Schnittstelle gekapselt.
public interface CustomerDao {
    Customer save(String name, String email);
    List<Customer> findAll();
}
package at.aydin.lab.persistence.legacy;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public final class JdbcCustomerDao implements CustomerDao {
    private final String url;

    public JdbcCustomerDao(String url) {
        this.url = url;
        initialize();
    }

    private Connection connection() throws SQLException {
        return DriverManager.getConnection(url, "sa", "");
    }

    private void initialize() {
        String sql = "create table if not exists customer("
                + "id bigint generated by default as identity primary key, "
                + "name varchar(120), email varchar(180))";

        try (Connection connection = connection();
                Statement statement = connection.createStatement()) {
            statement.executeUpdate(sql);
        } catch (SQLException exception) {
            throw new IllegalStateException("Schema konnte nicht erstellt werden", exception);
        }
    }

    @Override
    public Customer save(String name, String email) {
        String sql = "insert into customer(name,email) values (?,?)";
        try (Connection connection = connection();
                PreparedStatement statement = connection.prepareStatement(
                        sql, Statement.RETURN_GENERATED_KEYS)) {
            statement.setString(1, name);
            statement.setString(2, email);
            statement.executeUpdate();

            try (ResultSet keys = statement.getGeneratedKeys()) {
                if (!keys.next()) {
                    throw new SQLException("Keine ID erhalten");
                }
                return new Customer(keys.getLong(1), name, email);
            }
        } catch (SQLException exception) {
            throw new IllegalStateException("Kunde konnte nicht gespeichert werden", exception);
        }
    }

    @Override
    public List<Customer> findAll() {
        List<Customer> result = new ArrayList<>();
        String sql = "select id,name,email from customer order by id";

        try (Connection connection = connection();
                Statement statement = connection.createStatement();
                ResultSet resultSet = statement.executeQuery(sql)) {
            while (resultSet.next()) {
                result.add(new Customer(
                        resultSet.getLong("id"),
                        resultSet.getString("name"),
                        resultSet.getString("email")));
            }
            return result;
        } catch (SQLException exception) {
            throw new IllegalStateException("Kunden konnten nicht gelesen werden", exception);
        }
    }
}
package at.aydin.lab.persistence.legacy;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

class JdbcCustomerDaoTest {
    @Test
    void persistsCustomer() {
        CustomerDao dao = new JdbcCustomerDao("jdbc:h2:mem:testlegacy;DB_CLOSE_DELAY=-1");
        dao.save("Test", "test@example.test");
        assertEquals(1, dao.findAll().size());
    }
}

Modern

package at.aydin.lab.persistence.modern;

import org.springframework.data.jpa.repository.JpaRepository;

// Design Pattern: Repository
// Zweck: Spring Data erzeugt die technische Implementierung aus dem Interface.
public interface CustomerRepository extends JpaRepository<CustomerEntity, Long> {
}
package at.aydin.lab.persistence.modern;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import static org.junit.jupiter.api.Assertions.assertEquals;

@DataJpaTest
class CustomerRepositoryTest {
    @Autowired
    CustomerRepository repository;
    @Test
    void persistsCustomer() {
        repository.save(new CustomerEntity("Test", "test@example.test"));
        assertEquals(1, repository.count());
    }
}
05Service LayerNeu in Modern · Legacy 0 / Modern 25 Zeilen · Ähnlichkeit 0%

Die moderne Variante ergänzt eine eigene Transaktions- und Fachlogikschicht.

Legacy-DateienModern-DateienEinordnung
CustomerService.javaNeu in Modern
Semantische Ähnlichkeit: 0%

Legacy

Kein Legacy-Gegenstück. Diese Verantwortung wurde neu eingeführt.

Modern

package at.aydin.lab.persistence.modern;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;

@Service
// Design Pattern: Service Layer
// Zweck: Transaktions- und Fachgrenze über dem Repository.
public class CustomerService {
    private final CustomerRepository repository;
    public CustomerService(CustomerRepository repository) {
        this.repository = repository;
    }

    @Transactional
    public CustomerEntity create(String name, String email) {
        return repository.save(new CustomerEntity(name, email));
    }

    @Transactional(readOnly = true)
    public List<CustomerEntity> findAll() {
        return repository.findAll();
    }
}
⌂ Cockpit