diff --git a/opp/core/pom.xml b/opp/core/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a573bc80b75482c62550aff5fb8d734f1fb7a459
--- /dev/null
+++ b/opp/core/pom.xml
@@ -0,0 +1,37 @@
+<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.example</groupId>
+        <artifactId>opp</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>core</artifactId>
+
+    <properties>
+        <maven.compiler.source>22</maven.compiler.source>
+        <maven.compiler.target>22</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+            <version>2.13.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>2.13.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+            <version>2.13.0</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/opp/core/src/main/java/Address.java b/opp/core/src/main/java/Address.java
new file mode 100644
index 0000000000000000000000000000000000000000..a6f7e39aff05cbf53c70460bfd93ced9920f269c
--- /dev/null
+++ b/opp/core/src/main/java/Address.java
@@ -0,0 +1,9 @@
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public record Address(
+        @JsonProperty String street,
+        @JsonProperty String house,
+        @JsonProperty String postalCode,
+        @JsonProperty String city
+) {
+}
diff --git a/opp/core/src/main/java/Gender.java b/opp/core/src/main/java/Gender.java
new file mode 100644
index 0000000000000000000000000000000000000000..986e6895e75fae933bdccdb116aecce11ffe3d05
--- /dev/null
+++ b/opp/core/src/main/java/Gender.java
@@ -0,0 +1,6 @@
+public enum Gender {
+    MALE,
+    FEMALE,
+    OTHER,
+    UNKNOWN;
+}
diff --git a/opp/core/src/main/java/Id.java b/opp/core/src/main/java/Id.java
new file mode 100644
index 0000000000000000000000000000000000000000..f2f2920f0ad5428c74386f29292602a746be7ed0
--- /dev/null
+++ b/opp/core/src/main/java/Id.java
@@ -0,0 +1,38 @@
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+
+import java.io.IOException;
+
+@JsonSerialize(using = Id.Serializer.class)
+public record Id<T>(String value)
+{
+
+    @Override public String toString(){ return value; }
+
+
+    public static class Serializer<T> extends StdSerializer<Id<T>>
+    {
+
+        public Serializer(){
+            this(null);
+        }
+
+        public Serializer(Class<Id<T>> cl){
+            super(cl);
+        }
+
+        @Override
+        public void serialize(
+                Id<T> id,
+                JsonGenerator json,
+                SerializerProvider provider
+        )
+                throws IOException {
+            json.writeString(id.value());
+        }
+
+    }
+
+}
diff --git a/opp/core/src/main/java/Patient.java b/opp/core/src/main/java/Patient.java
new file mode 100644
index 0000000000000000000000000000000000000000..28ad22aebcc23289e59bfbdb76db0a5bb14c27d1
--- /dev/null
+++ b/opp/core/src/main/java/Patient.java
@@ -0,0 +1,29 @@
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.time.LocalDate;
+
+public record Patient (
+        @JsonProperty
+        Id<Patient> id,
+
+        @JsonProperty
+        Gender gender,
+
+        @JsonProperty
+        String givenName,
+
+        @JsonProperty
+        String familyName,
+
+        @JsonProperty
+        @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
+        LocalDate birthDate,
+
+        @JsonProperty
+        Address address,
+
+        @JsonProperty
+        String healthInsurance
+) {
+}
diff --git a/opp/core/src/main/java/Person.java b/opp/core/src/main/java/Person.java
new file mode 100644
index 0000000000000000000000000000000000000000..4f90e7b36c1d640d8ba30540a709b72458f0674d
--- /dev/null
+++ b/opp/core/src/main/java/Person.java
@@ -0,0 +1,26 @@
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.time.LocalDate;
+
+public record Person (
+        @JsonProperty
+        Id<Person> id,
+
+        @JsonProperty
+        Gender gender,
+
+        @JsonProperty
+        String givenName,
+
+        @JsonProperty
+        String familyName,
+
+        @JsonProperty
+        @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
+        LocalDate birthDate,
+
+        @JsonProperty
+        Address address
+) {
+}
diff --git a/opp/core/src/main/java/Repository.java b/opp/core/src/main/java/Repository.java
new file mode 100644
index 0000000000000000000000000000000000000000..145bef94ca2a5ce7ac2be9256e9ac8fc9a4b88c8
--- /dev/null
+++ b/opp/core/src/main/java/Repository.java
@@ -0,0 +1,14 @@
+import java.util.Optional;
+
+public interface Repository {
+
+    Id<Patient> patientId();
+
+    void createPatient(Patient patient) throws Exception;
+
+    Optional<Patient> findPatient(Id<Patient> id);
+
+    Optional<Patient> deletePatient(Id<Patient> id) throws Exception;
+
+    // Hier dann die restlichen create/edit Methoden rein
+}
diff --git a/opp/jdbc-repo-impl/pom.xml b/opp/jdbc-repo-impl/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fcb0af4f7a95afa1e2d312fd79ae3e3adfa2774d
--- /dev/null
+++ b/opp/jdbc-repo-impl/pom.xml
@@ -0,0 +1,40 @@
+<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.example</groupId>
+        <artifactId>opp</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>jdbc-repo-impl</artifactId>
+
+    <properties>
+        <maven.compiler.source>22</maven.compiler.source>
+        <maven.compiler.target>22</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+            <version>42.7.3</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.example</groupId>
+            <artifactId>core</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/opp/jdbc-repo-impl/src/main/java/JDBCRepository.java b/opp/jdbc-repo-impl/src/main/java/JDBCRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..81fcc8bd04edf9c6a898574e84e9f4e65d8b32c1
--- /dev/null
+++ b/opp/jdbc-repo-impl/src/main/java/JDBCRepository.java
@@ -0,0 +1,206 @@
+import java.sql.*;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.util.Optional;
+
+import static java.util.UUID.randomUUID;
+
+
+class JDBCRepository implements Repository
+{
+
+  private final Connection conn;
+
+  private JDBCRepository(Connection conn){ 
+    this.conn = conn;
+  }
+
+
+  // Factory method
+  static JDBCRepository instance(){
+    try {
+      var conn =
+        DriverManager.getConnection(
+          System.getProperty("pms.repo.jdbc.url"),
+          System.getProperty("pms.repo.jdbc.user"),
+          System.getProperty("pms.repo.jdbc.password")
+        );
+
+      var repo = new JDBCRepository(conn);
+      repo.setup();
+      return repo;
+
+    } catch (SQLException e){
+      throw new RuntimeException(e);
+    }
+  }
+  
+
+  private static final String CREATE_PATIENT_TABLE = """
+    CREATE TABLE IF NOT EXISTS patients(
+      id VARCHAR(50) PRIMARY KEY,
+      gender VARCHAR(10) NOT NULL,
+      givenName VARCHAR(100) NOT NULL,
+      familyName VARCHAR(100) NOT NULL,
+      birthDate DATE NOT NULL,
+      street VARCHAR(50) NOT NULL,
+      house VARCHAR(50) NOT NULL,
+      postalCode VARCHAR(50) NOT NULL,
+      city VARCHAR(50) NOT NULL,
+      healthInsurance VARCHAR(40) NOT NULL
+    );
+  """;
+
+
+  // Set up DB tables etc.
+  void setup(){
+    try (var stmt = conn.createStatement()){
+
+      stmt.execute(CREATE_PATIENT_TABLE); 
+
+    } catch (SQLException e){
+      throw new RuntimeException(e);
+    }
+  }
+
+
+  private static String quoted(String s){
+    return String.format("'%s'",s);
+  }
+
+  private static String sqlValue(Object obj){
+
+    return switch(obj){
+      case LocalDate date -> quoted(Date.valueOf(date).toString());
+      case Instant t      -> quoted(Timestamp.from(t).toString());
+      case Integer n      -> Integer.toString(n);
+      case Long n         -> Long.toString(n);
+      case Double n       -> Double.toString(n);
+      default             -> quoted(obj.toString());
+    };
+
+  }
+
+
+  private static Patient readPatientFromRow(ResultSet rs) throws SQLException {
+    return new Patient(
+      new Id<>(rs.getString("id")),
+      Gender.valueOf(rs.getString("gender")),
+      rs.getString("givenName"),
+      rs.getString("familyName"),
+      rs.getDate("birthDate").toLocalDate(),
+      new Address(
+              rs.getString("street"),
+              rs.getString("house"),
+              rs.getString("postalCode"),
+              rs.getString("city")
+      ),
+      rs.getString("healthInsurance")
+    );
+  }
+
+
+  private static String insertSQL(Patient patient){
+    return
+      "INSERT INTO patients(" + 
+        "id,gender,givenName,familyName,birthDate," +
+        "street,house,postalCode,city,healthInsurance" +
+      ") VALUES (" + 
+        sqlValue(patient.id().value()) + "," +
+        sqlValue(patient.gender()) + "," +
+        sqlValue(patient.givenName()) + "," +
+        sqlValue(patient.familyName()) + "," +
+        sqlValue(patient.birthDate()) + "," +
+        sqlValue(patient.address().street()) + "," +
+        sqlValue(patient.address().house()) + "," +
+        sqlValue(patient.address().postalCode()) + "," +
+        sqlValue(patient.address().city()) + "," +
+        sqlValue(patient.healthInsurance()) +
+      ");";
+  }
+
+  private static String updateSQL(Patient patient){
+    return
+      "UPDATE patients SET " +
+        "gender = " + sqlValue(patient.gender()) + "," +
+        "givenName = " + sqlValue(patient.givenName()) + "," +
+        "familyName = " + sqlValue(patient.familyName()) + "," +
+        "birthDate = " + sqlValue(patient.birthDate()) + "," +
+        "street = " + sqlValue(patient.address().street()) + "," +
+        "house = " + sqlValue(patient.address().house()) + "," +
+        "postalCode = " + sqlValue(patient.address().postalCode()) + "," +
+        "city = " + sqlValue(patient.address().city()) + "," +
+        "healthInsurance = " + sqlValue(patient.healthInsurance()) + " " +
+      "WHERE id = " + sqlValue(patient.id().value()) + ";";
+  }
+
+
+
+  @Override
+  public Id<Patient> patientId(){
+
+    var id = new Id<Patient>(randomUUID().toString());
+
+    return findPatient(id).isEmpty() ? id : patientId();
+  }
+
+
+  @Override
+  public void createPatient(Patient patient) throws SQLException {
+
+    try (
+      var stmt = conn.createStatement()
+    ){
+      var sql =
+        findPatient(patient.id()).isPresent() ?
+          updateSQL(patient) :
+          insertSQL(patient);
+
+      stmt.executeUpdate(sql);
+
+    } catch (SQLException e){
+      throw new RuntimeException(e);
+    }
+
+  }
+
+
+  @Override
+  public Optional<Patient> findPatient(Id<Patient> id){
+    try (
+      var result =
+        conn.createStatement()
+          .executeQuery("SELECT * FROM patients WHERE id = " + sqlValue(id.value()) + ";")
+    ){
+      return
+        result.next() ?
+          Optional.of(readPatientFromRow(result)) :
+          Optional.empty();
+
+    } catch (SQLException e){
+      throw new RuntimeException(e);
+    }
+  }
+
+
+  @Override
+  public Optional<Patient> deletePatient(Id<Patient> id) throws SQLException {
+
+    var patient = findPatient(id);
+
+    patient.ifPresent(
+      p -> {
+        try {
+          conn.createStatement()
+           .executeUpdate("DELETE FROM patients WHERE id = " + quoted(id.value()) + ";");
+        } catch (SQLException e){
+          throw new RuntimeException(e);
+        }
+      }
+    );
+
+    return patient;
+  }
+
+
+}
diff --git a/opp/jdbc-repo-impl/src/test/java/Tests.java b/opp/jdbc-repo-impl/src/test/java/Tests.java
new file mode 100644
index 0000000000000000000000000000000000000000..9c089048e5423e883adb3d061971dcfaaa2aa1af
--- /dev/null
+++ b/opp/jdbc-repo-impl/src/test/java/Tests.java
@@ -0,0 +1,64 @@
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.time.LocalDate;
+
+import static org.junit.Assert.*;
+import static org.junit.Assert.assertTrue;
+
+
+public final class Tests
+{
+
+  private static Repository repo = null;
+
+  private static Patient testPatient = null;
+
+  @BeforeClass
+  public static void init() throws Exception {
+
+    System.setProperty("pms.repo.jdbc.url",      "jdbc:postgresql:postgres");
+    System.setProperty("pms.repo.jdbc.user",     "postgres");
+    System.setProperty("pms.repo.jdbc.password", "1234");
+
+    repo = JDBCRepository.instance();
+
+    testPatient = new Patient(
+            new Id<>("1111"),
+            Gender.MALE,
+            "Hans",
+            "Guenther",
+            LocalDate.of(1999, 01, 01),
+            new Address("Musterstraße", "12", "12345", "Beispielhausen"),
+            "AOK");
+  }
+
+  @Test
+  public void testPatientSave(){
+
+    try {
+      repo.createPatient(testPatient);
+    } catch (Exception e){
+      e.printStackTrace();
+    }
+
+    assertTrue(
+      repo.findPatient(testPatient.id()).isPresent()
+    );
+  }
+
+
+  @Test
+  public void testPatientDelete(){
+
+    try {
+      repo.deletePatient(testPatient.id());
+    } catch (Exception e){
+      e.printStackTrace();
+    }
+
+    assertTrue(
+      repo.findPatient(testPatient.id()).isEmpty()
+    );
+  }
+}
diff --git a/opp/pom.xml b/opp/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7b50b5f510aafc4b75be28155a0d5309138e693d
--- /dev/null
+++ b/opp/pom.xml
@@ -0,0 +1,22 @@
+<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.example</groupId>
+    <artifactId>opp</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+    <modules>
+        <module>core</module>
+        <module>jdbc-repo-impl</module>
+    </modules>
+
+    <properties>
+        <maven.compiler.source>22</maven.compiler.source>
+        <maven.compiler.target>22</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+</project>
\ No newline at end of file