DAO mit handgeschriebenem JDBC
SQL, Connection-Handling, Schemaerzeugung und Mapping liegen in einer konkreten DAO-Klasse.
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.
SQL, Connection-Handling, Schemaerzeugung und Mapping liegen in einer konkreten DAO-Klasse.
Spring Data erzeugt die Repository-Implementierung; eine Service Layer bildet die Transaktionsgrenze.
Die Ähnlichkeit ist eine technische Orientierung auf normalisiertem Quelltext. Sie ersetzt keine fachliche Bewertung.
| Vergleichsgruppe | Legacy-Dateien | Modern-Dateien | Legacy-Zeilen | Modern-Zeilen | Ähnlichkeit |
|---|---|---|---|---|---|
| Build-Konfiguration | 1 | 1 | 35 | 43 | 56% |
| Bootstrap und Datenbankkonfiguration | 1 | 2 | 12 | 24 | 12% |
| Domänen-/Persistenzmodell | 1 | 1 | 4 | 41 | 6% |
| Datenzugriff und Test | 3 | 2 | 100 | 25 | 5% |
| Service Layer | 0 | 1 | 0 | 25 | 0% |
Das Pair-POM bindet die Legacy- und Modern-Submodule zusammen und gehört deshalb ebenfalls zur vollständigen Codeabdeckung.
JDBC-/JPA- und Testabhängigkeiten werden verglichen.
| Legacy-Dateien | Modern-Dateien | Einordnung |
|---|---|---|
| pom.xml | pom.xml | Direktvergleich Semantische Ähnlichkeit: 56% |
<?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><?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>Manuelles Setup wird durch Spring Boot und Properties ersetzt.
| Legacy-Dateien | Modern-Dateien | Einordnung |
|---|---|---|
| PersistenceLegacyApplication.java | PersistenceModernApplication.java application.properties | Direktvergleich Semantische Ähnlichkeit: 12% |
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);
}
}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);
};
}
}spring.datasource.url=jdbc:h2:mem:modern;DB_CLOSE_DELAY=-1
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.open-in-view=falsePOJO und persistierbare Entity werden verglichen.
| Legacy-Dateien | Modern-Dateien | Einordnung |
|---|---|---|
| Customer.java | CustomerEntity.java | Direktvergleich Semantische Ähnlichkeit: 6% |
package at.aydin.lab.persistence.legacy;
public record Customer(long id, String name, String email) {
}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 + "]";
}
}DAO-Interface plus JDBC-Implementierung wird durch Spring Data Repository ersetzt.
| Legacy-Dateien | Modern-Dateien | Einordnung |
|---|---|---|
| CustomerDao.java JdbcCustomerDao.java JdbcCustomerDaoTest.java | CustomerRepository.java CustomerRepositoryTest.java | Direktvergleich Semantische Ähnlichkeit: 5% |
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());
}
}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());
}
}Die moderne Variante ergänzt eine eigene Transaktions- und Fachlogikschicht.
| Legacy-Dateien | Modern-Dateien | Einordnung |
|---|---|---|
| — | CustomerService.java | Neu in Modern Semantische Ähnlichkeit: 0% |
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();
}
}