diff --git a/jdbc/jmolecules/pom.xml b/jdbc/jmolecules/pom.xml
new file mode 100644
index 00000000..b2262476
--- /dev/null
+++ b/jdbc/jmolecules/pom.xml
@@ -0,0 +1,69 @@
+
+ 4.0.0
+
+
+ org.springframework.data.examples
+ spring-data-jdbc-examples
+ 2.0.0.BUILD-SNAPSHOT
+
+
+ Spring Data JDBC - jMolecules Example
+ spring-data-jdbc-jmolecules
+
+
+ 2021.0.0-SNAPSHOT
+ 1.2.0
+ 0.2.0
+
+
+
+
+
+ com.h2database
+ h2
+ runtime
+
+
+
+
+
+ org.jmolecules.integrations
+ jmolecules-spring
+ ${jmolecules-integration.version}
+
+
+
+ org.jmolecules
+ jmolecules-events
+ ${jmolecules.version}
+
+
+
+
+
+
+
+ net.bytebuddy
+ byte-buddy-maven-plugin
+ ${byte-buddy.version}
+
+
+
+ transform
+
+
+
+
+
+ org.jmolecules.integrations
+ jmolecules-bytebuddy
+ ${jmolecules-integration.version}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/Application.java b/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/Application.java
new file mode 100644
index 00000000..ce4703ee
--- /dev/null
+++ b/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/Application.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.jdbc.jmolecules;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * @author Oliver Drotbohm
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/customer/Address.java b/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/customer/Address.java
new file mode 100644
index 00000000..5e2fce82
--- /dev/null
+++ b/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/customer/Address.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.jdbc.jmolecules.customer;
+
+import lombok.Value;
+
+import org.jmolecules.ddd.annotation.ValueObject;
+
+@Value
+@ValueObject
+public class Address {
+ private final String street, city, zipCode;
+}
diff --git a/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/customer/Customer.java b/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/customer/Customer.java
new file mode 100644
index 00000000..ad3312d6
--- /dev/null
+++ b/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/customer/Customer.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2020-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.jdbc.jmolecules.customer;
+
+import example.springdata.jdbc.jmolecules.customer.Customer.CustomerId;
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.Value;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.jmolecules.ddd.types.AggregateRoot;
+import org.jmolecules.ddd.types.Identifier;
+import org.springframework.data.annotation.PersistenceConstructor;
+import org.springframework.util.Assert;
+
+/**
+ * @author Oliver Drotbohm
+ */
+@Getter
+@ToString
+@AllArgsConstructor(access = AccessLevel.PRIVATE, onConstructor = @__(@PersistenceConstructor))
+public class Customer implements AggregateRoot {
+
+ private final CustomerId id;
+ private @Setter String firstname, lastname;
+ private List addresses;
+
+ public Customer(String firstname, String lastname, Address address) {
+
+ Assert.notNull(address, "Address must not be null!");
+
+ this.id = CustomerId.of(UUID.randomUUID().toString());
+
+ this.firstname = firstname;
+ this.lastname = lastname;
+
+ this.addresses = new ArrayList<>();
+ this.addresses.add(address);
+ }
+
+ @Value(staticConstructor = "of")
+ public static class CustomerId implements Identifier {
+ private final String id;
+ }
+}
diff --git a/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/customer/Customers.java b/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/customer/Customers.java
new file mode 100644
index 00000000..d7ae0563
--- /dev/null
+++ b/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/customer/Customers.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2020-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.jdbc.jmolecules.customer;
+
+import example.springdata.jdbc.jmolecules.customer.Customer.CustomerId;
+
+import org.jmolecules.ddd.types.Repository;
+import org.jmolecules.spring.AssociationResolver;
+
+/**
+ * @author Oliver Drotbohm
+ */
+public interface Customers extends Repository, AssociationResolver {
+ Customer save(Customer customer);
+}
diff --git a/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/order/LineItem.java b/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/order/LineItem.java
new file mode 100644
index 00000000..85fd2e6f
--- /dev/null
+++ b/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/order/LineItem.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2020-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.jdbc.jmolecules.order;
+
+import lombok.Value;
+
+import org.jmolecules.ddd.annotation.ValueObject;
+
+@Value
+@ValueObject
+public class LineItem {
+ String description;
+}
diff --git a/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/order/Order.java b/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/order/Order.java
new file mode 100644
index 00000000..fba4db25
--- /dev/null
+++ b/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/order/Order.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2020-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.jdbc.jmolecules.order;
+
+import example.springdata.jdbc.jmolecules.customer.Customer;
+import example.springdata.jdbc.jmolecules.customer.Customer.CustomerId;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+import lombok.Value;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.jmolecules.ddd.types.AggregateRoot;
+import org.jmolecules.ddd.types.Association;
+import org.jmolecules.ddd.types.Identifier;
+import org.springframework.data.relational.core.mapping.Column;
+import org.springframework.data.relational.core.mapping.Table;
+
+/**
+ * @author Oliver Drotbohm
+ */
+@Table("MY_ORDER")
+@Getter
+@ToString
+@RequiredArgsConstructor
+public class Order implements AggregateRoot {
+
+ private final OrderId id;
+ private @Column("FOO") List lineItems;
+ private Association customer;
+
+ public Order(Customer customer) {
+
+ this.id = OrderId.of(UUID.randomUUID());
+ this.customer = Association.forAggregate(customer);
+ this.lineItems = new ArrayList<>();
+ }
+
+ public Order addLineItem(String description) {
+
+ LineItem item = new LineItem(description);
+
+ this.lineItems.add(item);
+
+ return this;
+ }
+
+ @Value(staticConstructor = "of")
+ public static class OrderId implements Identifier {
+
+ private final UUID orderId;
+
+ public static OrderId create() {
+ return OrderId.of(UUID.randomUUID());
+ }
+ }
+}
diff --git a/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/order/Orders.java b/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/order/Orders.java
new file mode 100644
index 00000000..0f178d63
--- /dev/null
+++ b/jdbc/jmolecules/src/main/java/example/springdata/jdbc/jmolecules/order/Orders.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2020-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.jdbc.jmolecules.order;
+
+import example.springdata.jdbc.jmolecules.order.Order.OrderId;
+
+import org.jmolecules.ddd.types.Repository;
+import org.jmolecules.spring.AssociationResolver;
+
+/**
+ * @author Oliver Drotbohm
+ */
+public interface Orders extends Repository, AssociationResolver {
+ Order save(Order order);
+}
diff --git a/jdbc/jmolecules/src/main/resources/schema.sql b/jdbc/jmolecules/src/main/resources/schema.sql
new file mode 100644
index 00000000..4a75e4b7
--- /dev/null
+++ b/jdbc/jmolecules/src/main/resources/schema.sql
@@ -0,0 +1,28 @@
+CREATE TABLE IF NOT EXISTS customer (
+ id VARCHAR(100) PRIMARY KEY,
+ firstname VARCHAR(100),
+ lastname VARCHAR(100)
+);
+
+CREATE TABLE IF NOT EXISTS address (
+ street VARCHAR(100),
+ city VARCHAR(100),
+ zip_code VARCHAR(100),
+ customer VARCHAR(100),
+ customer_key VARCHAR(100)
+);
+
+CREATE TABLE IF NOT EXISTS my_order (
+ id VARCHAR(100),
+ customer VARCHAR(100)
+);
+
+CREATE TABLE IF NOT EXISTS line_item (
+ my_order_key VARCHAR(100),
+ description VARCHAR(100),
+ foo VARCHAR(100)
+);
+
+// CREATE TABLE IF NOT EXISTS Lego_Set (id INTEGER, name VARCHAR(100), min_Age INTEGER, max_Age INTEGER);
+// CREATE TABLE IF NOT EXISTS Handbuch (handbuch_id INTEGER, author VARCHAR(100), text CLOB);
+// CREATE TABLE IF NOT EXISTS Model (name VARCHAR(100), description CLOB, lego_set INTEGER);
diff --git a/jdbc/jmolecules/src/test/java/example/springdata/jdbc/jmolecules/ApplicationIntegrationTests.java b/jdbc/jmolecules/src/test/java/example/springdata/jdbc/jmolecules/ApplicationIntegrationTests.java
new file mode 100644
index 00000000..cdaf6fd1
--- /dev/null
+++ b/jdbc/jmolecules/src/test/java/example/springdata/jdbc/jmolecules/ApplicationIntegrationTests.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2020-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.jdbc.jmolecules;
+
+import static org.assertj.core.api.Assertions.*;
+
+import example.springdata.jdbc.jmolecules.customer.Address;
+import example.springdata.jdbc.jmolecules.customer.Customer;
+import example.springdata.jdbc.jmolecules.customer.Customers;
+import example.springdata.jdbc.jmolecules.order.Order;
+import example.springdata.jdbc.jmolecules.order.Orders;
+import lombok.RequiredArgsConstructor;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
+import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
+import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
+
+/**
+ * @author Oliver Drotbohm
+ */
+@SpringBootTest
+@RequiredArgsConstructor
+class ApplicationIntegrationTests {
+
+ private final ConfigurableApplicationContext context;
+
+ @Test
+ void exposesAssociationInMetamodel() {
+
+ JdbcMappingContext mapping = context.getBean(JdbcMappingContext.class);
+ RelationalPersistentEntity> entity = mapping.getRequiredPersistentEntity(Order.class);
+ RelationalPersistentProperty customer = entity.getRequiredPersistentProperty("customer");
+
+ assertThat(customer.isAssociation()).isTrue();
+ }
+
+ @Test
+ void persistsDomainModel() {
+
+ Address address = new Address("41 Greystreet", "Dreaming Tree", "2731");
+
+ Customers customers = context.getBean(Customers.class);
+ Customer customer = customers.save(new Customer("Dave", "Matthews", address));
+
+ customer.setFirstname("Carter");
+ customer = customers.save(customer);
+
+ Orders orders = context.getBean(Orders.class);
+
+ Order order = new Order(customer)
+ .addLineItem("Foo")
+ .addLineItem("Bar");
+
+ Order result = orders.save(order);
+
+ assertThat(customers.resolveRequired(result.getCustomer()));
+ }
+}
diff --git a/jdbc/pom.xml b/jdbc/pom.xml
index 398da725..f7a9dada 100644
--- a/jdbc/pom.xml
+++ b/jdbc/pom.xml
@@ -19,6 +19,7 @@
basics
mybatis
+ jmolecules
jooq