From 7e606707030f67286917eefeba03a1693a59f862 Mon Sep 17 00:00:00 2001 From: Lilly <46890129+RainbowDashLabs@users.noreply.github.com> Date: Sat, 25 May 2024 15:53:44 +0200 Subject: [PATCH] first partially working poc --- sadu-jackson-mapper/build.gradle.kts | 14 +++ .../chojo/sadu/jackson/JacksonRowMapper.java | 85 +++++++++++++++++++ .../sadu/jackson/JacksonRowMapperFactory.java | 36 ++++++++ .../jackson/JacksonRowMapperRegistry.java | 54 ++++++++++++ .../chojo/sadu/jackson/ResultSetMapper.java | 40 --------- ....java => JacksonRowMapperFactoryTest.java} | 2 +- .../java/de/chojo/sadu/jackson/TestObj.java | 28 ++++++ .../jackson/databases/TestPostgreSQL.java | 53 ++++++++++++ .../sadu/jackson/setup/MariaDBDatabase.java | 46 ++++++++++ .../sadu/jackson/setup/MySQLDatabase.java | 46 ++++++++++ .../sadu/jackson/setup/PostgresDatabase.java | 58 +++++++++++++ .../resources/database/postgresql/1/setup.sql | 8 ++ .../src/test/resources/database/version | 1 + .../chojo/sadu/mapper/IRowMapperRegistry.java | 39 +++++++++ .../chojo/sadu/mapper/RowMapperRegistry.java | 23 +++-- .../sadu/mapper/rowmapper/IRowMapper.java | 38 +++++++++ .../sadu/mapper/rowmapper/RowMapper.java | 9 +- .../mapper/rowmapper/RowMapperBuilder.java | 6 +- .../ConnectedQueryConfiguration.java | 3 +- .../configuration/QueryConfiguration.java | 9 +- .../QueryConfigurationBuilder.java | 5 +- .../converter/StandardValueConverter.java | 6 ++ .../queries/converter/ValueConverter.java | 6 ++ settings.gradle.kts | 4 + 24 files changed, 560 insertions(+), 59 deletions(-) create mode 100644 sadu-jackson-mapper/src/main/java/de/chojo/sadu/jackson/JacksonRowMapper.java create mode 100644 sadu-jackson-mapper/src/main/java/de/chojo/sadu/jackson/JacksonRowMapperFactory.java create mode 100644 sadu-jackson-mapper/src/main/java/de/chojo/sadu/jackson/JacksonRowMapperRegistry.java delete mode 100644 sadu-jackson-mapper/src/main/java/de/chojo/sadu/jackson/ResultSetMapper.java rename sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/{ResultSetMapperTest.java => JacksonRowMapperFactoryTest.java} (88%) create mode 100644 sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/TestObj.java create mode 100644 sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/databases/TestPostgreSQL.java create mode 100644 sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/setup/MariaDBDatabase.java create mode 100644 sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/setup/MySQLDatabase.java create mode 100644 sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/setup/PostgresDatabase.java create mode 100644 sadu-jackson-mapper/src/test/resources/database/postgresql/1/setup.sql create mode 100644 sadu-jackson-mapper/src/test/resources/database/version create mode 100644 sadu-mapper/src/main/java/de/chojo/sadu/mapper/IRowMapperRegistry.java create mode 100644 sadu-mapper/src/main/java/de/chojo/sadu/mapper/rowmapper/IRowMapper.java diff --git a/sadu-jackson-mapper/build.gradle.kts b/sadu-jackson-mapper/build.gradle.kts index b01f6ce5..3e0cbd19 100644 --- a/sadu-jackson-mapper/build.gradle.kts +++ b/sadu-jackson-mapper/build.gradle.kts @@ -1,4 +1,18 @@ dependencies { api(project(":sadu-mapper")) api("com.fasterxml.jackson.core", "jackson-databind", "2.17.1") + + testImplementation(project(":sadu-queries")) + testImplementation(project(":sadu-postgresql")) + testImplementation(project(":sadu-mariadb")) + testImplementation(project(":sadu-mysql")) + testImplementation(project(":sadu-sqlite")) + testImplementation(project(":sadu-datasource")) + testImplementation(testlibs.bundles.database.postgres) + testImplementation(testlibs.bundles.database.mariadb) + testImplementation(testlibs.bundles.database.mysql) + testImplementation(testlibs.driver.sqlite) + testImplementation(testlibs.slf4j.noop) + testImplementation(testlibs.bundles.junit) + testImplementation(libs.jackson.jsr310) } diff --git a/sadu-jackson-mapper/src/main/java/de/chojo/sadu/jackson/JacksonRowMapper.java b/sadu-jackson-mapper/src/main/java/de/chojo/sadu/jackson/JacksonRowMapper.java new file mode 100644 index 00000000..6971260d --- /dev/null +++ b/sadu-jackson-mapper/src/main/java/de/chojo/sadu/jackson/JacksonRowMapper.java @@ -0,0 +1,85 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.jackson; + +import com.fasterxml.jackson.databind.ObjectMapper; +import de.chojo.sadu.core.types.SqlType; +import de.chojo.sadu.jackson.exception.UnknownTypeException; +import de.chojo.sadu.mapper.IRowMapperRegistry; +import de.chojo.sadu.mapper.MapperConfig; +import de.chojo.sadu.mapper.rowmapper.IRowMapper; +import de.chojo.sadu.mapper.wrapper.Row; + +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class JacksonRowMapper implements IRowMapper { + private final Class clazz; + private final ObjectMapper objectMapper; + private final IRowMapperRegistry registry; + + public JacksonRowMapper(Class clazz, ObjectMapper objectMapper, IRowMapperRegistry registry) { + this.clazz = clazz; + this.objectMapper = objectMapper; + this.registry = registry; + } + + @Override + public T map(Row row) throws SQLException { + ResultSetMetaData meta = row.getMetaData(); + Map map = new HashMap<>(); + for (int index = 1; index < meta.getColumnCount() + 1; index++) { + // Maybe this works already + //map.put(meta.getColumnName(index), row.getObject(index)); + var type = meta.getColumnTypeName(index); + var forType = registry.findForType(type); + var mapper = forType.orElseThrow(() -> new UnknownTypeException(type)); + map.put(meta.getColumnName(index), mapper.map(row, index)); + } + + return objectMapper.convertValue(map, clazz); + } + + @Override + public T map(Row row, int index) throws SQLException { + throw new UnsupportedOperationException("A Jackson row Mapper can not map by index."); + } + + @Override + public boolean isWildcard() { + return false; + } + + @Override + public int applicable(ResultSet resultSet) throws SQLException { + return applicable(resultSet.getMetaData()); + } + + @Override + public int applicable(ResultSet resultSet, MapperConfig config) throws SQLException { + return applicable(resultSet.getMetaData(), config); + } + + @Override + public int applicable(ResultSetMetaData meta) throws SQLException { + return meta.getColumnCount(); + } + + @Override + public int applicable(ResultSetMetaData meta, MapperConfig config) throws SQLException { + return applicable(meta); + } + + @Override + public List types() { + return List.of(); + } +} diff --git a/sadu-jackson-mapper/src/main/java/de/chojo/sadu/jackson/JacksonRowMapperFactory.java b/sadu-jackson-mapper/src/main/java/de/chojo/sadu/jackson/JacksonRowMapperFactory.java new file mode 100644 index 00000000..b56f8d2b --- /dev/null +++ b/sadu-jackson-mapper/src/main/java/de/chojo/sadu/jackson/JacksonRowMapperFactory.java @@ -0,0 +1,36 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.jackson; + +import com.fasterxml.jackson.databind.ObjectMapper; +import de.chojo.sadu.jackson.exception.UnknownTypeException; +import de.chojo.sadu.mapper.IRowMapperRegistry; +import de.chojo.sadu.mapper.rowmapper.IRowMapper; +import de.chojo.sadu.mapper.rowmapper.RowMapper; +import de.chojo.sadu.mapper.wrapper.Row; + +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class JacksonRowMapperFactory { + private final IRowMapperRegistry registry; + private final ObjectMapper objectMapper; + private final Map, IRowMapper> mapper = new HashMap<>(); + + public JacksonRowMapperFactory(ObjectMapper objectMapper, IRowMapperRegistry registry) { + this.objectMapper = objectMapper; + this.registry = registry; + } + + @SuppressWarnings("unchecked") + public > V forClass(Class clazz) { + return (V) mapper.computeIfAbsent(clazz, key -> new JacksonRowMapper<>(key, objectMapper, registry)); + } +} diff --git a/sadu-jackson-mapper/src/main/java/de/chojo/sadu/jackson/JacksonRowMapperRegistry.java b/sadu-jackson-mapper/src/main/java/de/chojo/sadu/jackson/JacksonRowMapperRegistry.java new file mode 100644 index 00000000..22ba9831 --- /dev/null +++ b/sadu-jackson-mapper/src/main/java/de/chojo/sadu/jackson/JacksonRowMapperRegistry.java @@ -0,0 +1,54 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.jackson; + +import com.fasterxml.jackson.databind.ObjectMapper; +import de.chojo.sadu.mapper.IRowMapperRegistry; +import de.chojo.sadu.mapper.MapperConfig; +import de.chojo.sadu.mapper.exceptions.MappingException; +import de.chojo.sadu.mapper.rowmapper.IRowMapper; +import de.chojo.sadu.mapper.rowmapper.RowMapper; + +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.List; +import java.util.Optional; + +public class JacksonRowMapperRegistry implements IRowMapperRegistry { + private final JacksonRowMapperFactory factory; + private final IRowMapperRegistry registry; + + public JacksonRowMapperRegistry(ObjectMapper objectMapper, IRowMapperRegistry registry) { + this.registry = registry; + this.factory = new JacksonRowMapperFactory(objectMapper, registry); + } + + @Override + public List> mapper(Class clazz) { + return List.of(); + } + + @Override + public Optional> wildcard(Class clazz) { + return Optional.ofNullable(registry.wildcard(clazz).orElseGet(() -> factory.forClass(clazz))); + } + + @Override + public Optional> find(Class clazz, ResultSetMetaData meta, MapperConfig config) { + return wildcard(clazz); + } + + @Override + public > V findOrWildcard(Class clazz, ResultSetMetaData meta, MapperConfig config) throws MappingException, SQLException { + return (V) wildcard(clazz).get(); + } + + @Override + public Optional> findForType(String name) { + return Optional.empty(); + } +} diff --git a/sadu-jackson-mapper/src/main/java/de/chojo/sadu/jackson/ResultSetMapper.java b/sadu-jackson-mapper/src/main/java/de/chojo/sadu/jackson/ResultSetMapper.java deleted file mode 100644 index 8066a7bf..00000000 --- a/sadu-jackson-mapper/src/main/java/de/chojo/sadu/jackson/ResultSetMapper.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SPDX-License-Identifier: LGPL-3.0-or-later - * - * Copyright (C) RainbowDashLabs and Contributor - */ - -package de.chojo.sadu.jackson; - -import com.fasterxml.jackson.databind.ObjectMapper; -import de.chojo.sadu.mapper.RowMapperRegistry; -import de.chojo.sadu.mapper.wrapper.Row; - -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.util.HashMap; -import java.util.Map; - -public class ResultSetMapper { - private final RowMapperRegistry registry; - private final ObjectMapper objectMapper; - - public ResultSetMapper(ObjectMapper objectMapper, RowMapperRegistry registry) { - this.objectMapper = objectMapper; - this.registry = registry; - } - - public T convertRow(Row row, Class clazz) throws SQLException { - ResultSetMetaData meta = row.getMetaData(); - Map map = new HashMap<>(); - for (int index = 1; index < meta.getColumnCount() + 1; index++) { - map.put(meta.getColumnName(index), row.getObject(index)); -// var type = meta.getColumnTypeName(index); -// Optional> forType = registry.findForType(type); -// var mapper = forType.orElseThrow(() -> new UnknownTypeException(type)); -// map.put(meta.getColumnName(index), mapper.map(row, index)); - } - - return objectMapper.convertValue(map, clazz); - } -} diff --git a/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/ResultSetMapperTest.java b/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/JacksonRowMapperFactoryTest.java similarity index 88% rename from sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/ResultSetMapperTest.java rename to sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/JacksonRowMapperFactoryTest.java index 238dcb9a..e7b62427 100644 --- a/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/ResultSetMapperTest.java +++ b/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/JacksonRowMapperFactoryTest.java @@ -10,7 +10,7 @@ import static org.junit.jupiter.api.Assertions.*; -class ResultSetMapperTest { +class JacksonRowMapperFactoryTest { @Test void convertRow() { diff --git a/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/TestObj.java b/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/TestObj.java new file mode 100644 index 00000000..c888378e --- /dev/null +++ b/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/TestObj.java @@ -0,0 +1,28 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.jackson; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.time.Instant; +import java.util.UUID; + +public record TestObj(int first, long second, String third, Instant fourth, UUID fifth) { + @JsonCreator + public TestObj(@JsonProperty("first") int first, + @JsonProperty("second") long second, + @JsonProperty("third") String third, + @JsonProperty("fourth") Instant fourth, + @JsonProperty("fifth") UUID fifth) { + this.first = first; + this.second = second; + this.third = third; + this.fourth = fourth; + this.fifth = fifth; + } +} diff --git a/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/databases/TestPostgreSQL.java b/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/databases/TestPostgreSQL.java new file mode 100644 index 00000000..cbc813b0 --- /dev/null +++ b/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/databases/TestPostgreSQL.java @@ -0,0 +1,53 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.jackson.databases; + +import de.chojo.sadu.jackson.TestObj; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.time.Instant; +import java.util.UUID; +import java.util.stream.Stream; + +import static de.chojo.sadu.jackson.setup.PostgresDatabase.createContainer; +import static de.chojo.sadu.queries.api.call.Call.call; +import static de.chojo.sadu.queries.api.query.Query.query; +import static de.chojo.sadu.queries.converter.StandardValueConverter.INSTANT_MILLIS; +import static de.chojo.sadu.queries.converter.StandardValueConverter.INSTANT_TIMESTAMP; +import static de.chojo.sadu.queries.converter.StandardValueConverter.UUID_STRING; + +public class TestPostgreSQL { + @BeforeEach + void setup() throws Exception { + createContainer(); + } + + public static Stream objects() { + return Stream.of( + new TestObj(1324, 78644877545455L, "test", Instant.now(), UUID.randomUUID()) + ); + } + + @ParameterizedTest + @MethodSource("objects") + public void testRead(TestObj obj) { + query("INSERT INTO test(first, second, third, fourth, fifth) VALUES (?,?,?,?,?::UUID)") + .single(call().bind(obj.first()).bind(obj.second()).bind(obj.third()).bind(obj.fourth(), INSTANT_TIMESTAMP).bind(obj.fifth(), UUID_STRING)) + .insert(); + + var result = query("SELECT * FROM test") + .single() + .mapAs(TestObj.class) + .first() + .get(); + + Assertions.assertEquals(obj, result); + } +} diff --git a/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/setup/MariaDBDatabase.java b/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/setup/MariaDBDatabase.java new file mode 100644 index 00000000..f1de83e3 --- /dev/null +++ b/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/setup/MariaDBDatabase.java @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.jackson.setup; + +import de.chojo.sadu.datasource.DataSourceCreator; +import de.chojo.sadu.mariadb.databases.MariaDb; +import de.chojo.sadu.postgresql.databases.PostgreSql; +import de.chojo.sadu.updater.SqlUpdater; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; + +import javax.sql.DataSource; +import java.io.IOException; +import java.sql.SQLException; + +public class MariaDBDatabase { + public static Database createContainer() throws IOException, SQLException { + GenericContainer self = new GenericContainer<>(DockerImageName.parse("mariadb:latest")) + .withExposedPorts(3306) + .withEnv("MARIADB_ROOT_PASSWORD", "root") + .waitingFor(Wait.forLogMessage(".*mariadbd: ready for connections.*", 2)); + self.start(); + + DataSource dc = DataSourceCreator.create(MariaDb.get()) + .configure(c -> c.host(self.getHost()).port(self.getFirstMappedPort())).create() + .usingPassword("root") + .usingUsername("root") + .build(); + + SqlUpdater.builder(dc, MariaDb.get()) + .execute(); + + return new Database(self, dc); + } + + public static record Database(GenericContainer container, DataSource dataSource) { + public void close() { + container.close(); + } + } +} diff --git a/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/setup/MySQLDatabase.java b/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/setup/MySQLDatabase.java new file mode 100644 index 00000000..75360ab3 --- /dev/null +++ b/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/setup/MySQLDatabase.java @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.jackson.setup; + +import de.chojo.sadu.datasource.DataSourceCreator; +import de.chojo.sadu.mariadb.databases.MariaDb; +import de.chojo.sadu.mysql.databases.MySql; +import de.chojo.sadu.updater.SqlUpdater; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; + +import javax.sql.DataSource; +import java.io.IOException; +import java.sql.SQLException; + +public class MySQLDatabase { + public static Database createContainer() throws IOException, SQLException { + GenericContainer self = new GenericContainer<>(DockerImageName.parse("mysql:latest")) + .withExposedPorts(3306) + .withEnv("MYSQL_ROOT_PASSWORD", "root") + .waitingFor(Wait.forLogMessage(".*port: 3306 MySQL Community Server - GPL.*", 2)); + self.start(); + + DataSource dc = DataSourceCreator.create(MySql.get()) + .configure(c -> c.host(self.getHost()).port(self.getFirstMappedPort())).create() + .usingPassword("root") + .usingUsername("root") + .build(); + + SqlUpdater.builder(dc, MySql.get()) + .execute(); + + return new Database(self, dc); + } + + public static record Database(GenericContainer container, DataSource dataSource) { + public void close() { + container.close(); + } + } +} diff --git a/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/setup/PostgresDatabase.java b/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/setup/PostgresDatabase.java new file mode 100644 index 00000000..9426c6ae --- /dev/null +++ b/sadu-jackson-mapper/src/test/java/de/chojo/sadu/jackson/setup/PostgresDatabase.java @@ -0,0 +1,58 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.jackson.setup; + +import com.fasterxml.jackson.databind.ObjectMapper; +import de.chojo.sadu.datasource.DataSourceCreator; +import de.chojo.sadu.jackson.JacksonRowMapperRegistry; +import de.chojo.sadu.mapper.RowMapperRegistry; +import de.chojo.sadu.postgresql.databases.PostgreSql; +import de.chojo.sadu.postgresql.mapper.PostgresqlMapper; +import de.chojo.sadu.queries.configuration.QueryConfiguration; +import de.chojo.sadu.updater.SqlUpdater; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; + +import javax.sql.DataSource; +import java.io.IOException; +import java.sql.SQLException; + +public class PostgresDatabase { + public static Database createContainer() throws IOException, SQLException { + GenericContainer self = new GenericContainer<>(DockerImageName.parse("postgres:latest")) + .withExposedPorts(5432) + .withEnv("POSTGRES_USER", "postgres") + .withEnv("POSTGRES_PASSWORD", "postgres") + .waitingFor(Wait.forLogMessage(".*database system is ready to accept connections.*", 2)); + self.start(); + + DataSource dc = DataSourceCreator.create(PostgreSql.get()) + .configure(c -> c.host(self.getHost()).port(self.getFirstMappedPort())).create() + .usingPassword("postgres") + .usingUsername("postgres") + .build(); + + SqlUpdater.builder(dc, PostgreSql.get()) + .execute(); + + RowMapperRegistry registry = new RowMapperRegistry().register(PostgresqlMapper.getDefaultMapper()); + JacksonRowMapperRegistry jacksonRegistry = new JacksonRowMapperRegistry(new ObjectMapper().findAndRegisterModules(), registry); + + QueryConfiguration.setDefault(QueryConfiguration.builder(dc) + .setRowMapperRegistry(jacksonRegistry) + .build()); + + return new Database(self, dc); + } + + public static record Database(GenericContainer container, DataSource dataSource) { + public void close() { + container.close(); + } + } +} diff --git a/sadu-jackson-mapper/src/test/resources/database/postgresql/1/setup.sql b/sadu-jackson-mapper/src/test/resources/database/postgresql/1/setup.sql new file mode 100644 index 00000000..7b500d54 --- /dev/null +++ b/sadu-jackson-mapper/src/test/resources/database/postgresql/1/setup.sql @@ -0,0 +1,8 @@ +CREATE TABLE test +( + first INTEGER, + second BIGINT, + third TEXT, + fourth TIMESTAMP, + fifth UUID +); diff --git a/sadu-jackson-mapper/src/test/resources/database/version b/sadu-jackson-mapper/src/test/resources/database/version new file mode 100644 index 00000000..d3827e75 --- /dev/null +++ b/sadu-jackson-mapper/src/test/resources/database/version @@ -0,0 +1 @@ +1.0 diff --git a/sadu-mapper/src/main/java/de/chojo/sadu/mapper/IRowMapperRegistry.java b/sadu-mapper/src/main/java/de/chojo/sadu/mapper/IRowMapperRegistry.java new file mode 100644 index 00000000..f5ef0be4 --- /dev/null +++ b/sadu-mapper/src/main/java/de/chojo/sadu/mapper/IRowMapperRegistry.java @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.mapper; + +import de.chojo.sadu.mapper.exceptions.MappingException; +import de.chojo.sadu.mapper.rowmapper.IRowMapper; +import de.chojo.sadu.mapper.rowmapper.RowMapper; + +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.List; +import java.util.Optional; + +public interface IRowMapperRegistry { + List> mapper(Class clazz); + + @SuppressWarnings("unchecked") + Optional> wildcard(Class clazz); + + default Optional> find(Class clazz, ResultSet set, MapperConfig config) throws SQLException { + return find(clazz, set.getMetaData(), config); + } + + @SuppressWarnings("unchecked") + Optional> find(Class clazz, ResultSetMetaData meta, MapperConfig config); + + default > V findOrWildcard(Class clazz, ResultSet set, MapperConfig config) throws MappingException, SQLException { + return findOrWildcard(clazz, set.getMetaData(), config); + } + + > V findOrWildcard(Class clazz, ResultSetMetaData meta, MapperConfig config) throws MappingException, SQLException; + + Optional> findForType(String name); +} diff --git a/sadu-mapper/src/main/java/de/chojo/sadu/mapper/RowMapperRegistry.java b/sadu-mapper/src/main/java/de/chojo/sadu/mapper/RowMapperRegistry.java index ee5dade8..d1b9ceaa 100644 --- a/sadu-mapper/src/main/java/de/chojo/sadu/mapper/RowMapperRegistry.java +++ b/sadu-mapper/src/main/java/de/chojo/sadu/mapper/RowMapperRegistry.java @@ -9,6 +9,7 @@ import de.chojo.sadu.core.types.SqlType; import de.chojo.sadu.mapper.exceptions.MappingAlreadyRegisteredException; import de.chojo.sadu.mapper.exceptions.MappingException; +import de.chojo.sadu.mapper.rowmapper.IRowMapper; import de.chojo.sadu.mapper.rowmapper.RowMapper; import java.sql.ResultSet; @@ -25,13 +26,17 @@ /** * Class to register {@link RowMapper} to map rows to objects. */ -public class RowMapperRegistry { +public class RowMapperRegistry implements IRowMapperRegistry { private final Map, List>> mapper = new HashMap<>(); private final Map>> types = new HashMap<>(); public RowMapperRegistry() { } + public List> mapper(Class clazz) { + return mapper.getOrDefault(clazz, Collections.emptyList()); + } + /** * Registers a new mapper for a class. *

@@ -97,10 +102,6 @@ public RowMapperRegistry register(List> rowMapper) { return this; } - private List> mapper(Class clazz) { - return mapper.getOrDefault(clazz, Collections.emptyList()); - } - /** * Gets the wild card mapper if registered. * @@ -108,6 +109,7 @@ private List> mapper(Class clazz) { * @param type of mapper * @return mapper if exists */ + @Override @SuppressWarnings("unchecked") public Optional> wildcard(Class clazz) { return mapper(clazz).stream() @@ -128,6 +130,7 @@ public Optional> wildcard(Class clazz) { * @param return type of mapper * @return mapper when found */ + @Override public Optional> find(Class clazz, ResultSet set, MapperConfig config) throws SQLException { return find(clazz, set.getMetaData(), config); } @@ -144,6 +147,7 @@ public Optional> find(Class clazz, ResultSet set, MapperConf * @param return type of mapper * @return mapper when found */ + @Override @SuppressWarnings("unchecked") public Optional> find(Class clazz, ResultSetMetaData meta, MapperConfig config) { return mapper(clazz) @@ -170,7 +174,8 @@ public Optional> find(Class clazz, ResultSetMetaData meta, M * @return mapper when found * @throws MappingException when no mapper was found for this class and no wildcard mapper is registered. */ - public RowMapper findOrWildcard(Class clazz, ResultSet set, MapperConfig config) throws MappingException, SQLException { + @Override + public > V findOrWildcard(Class clazz, ResultSet set, MapperConfig config) throws MappingException, SQLException { return findOrWildcard(clazz, set.getMetaData(), config); } @@ -185,15 +190,17 @@ public RowMapper findOrWildcard(Class clazz, ResultSet set, MapperConf * @throws MappingException when no mapper was found for this class and no wildcard mapper is registered. * @throws SQLException if a database access error occurs */ - public RowMapper findOrWildcard(Class clazz, ResultSetMetaData meta, MapperConfig config) throws MappingException, SQLException { + @Override + public > V findOrWildcard(Class clazz, ResultSetMetaData meta, MapperConfig config) throws MappingException, SQLException { Optional> mapper = find(clazz, meta, config) .or(() -> wildcard(clazz)); if (mapper.isPresent()) { - return mapper.get(); + return (V) mapper.get(); } throw MappingException.create(clazz, meta); } + @Override public Optional> findForType(String name) { return Optional.ofNullable(types.get(name).get(0)); } diff --git a/sadu-mapper/src/main/java/de/chojo/sadu/mapper/rowmapper/IRowMapper.java b/sadu-mapper/src/main/java/de/chojo/sadu/mapper/rowmapper/IRowMapper.java new file mode 100644 index 00000000..daa18718 --- /dev/null +++ b/sadu-mapper/src/main/java/de/chojo/sadu/mapper/rowmapper/IRowMapper.java @@ -0,0 +1,38 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.mapper.rowmapper; + +import de.chojo.sadu.core.types.SqlType; +import de.chojo.sadu.mapper.MapperConfig; +import de.chojo.sadu.mapper.wrapper.Row; + +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.Collections; +import java.util.List; + +public interface IRowMapper extends RowMapping { + @Override + T map(Row row) throws SQLException; + + T map(Row row, int index) throws SQLException; + + boolean isWildcard(); + + int applicable(ResultSet resultSet) throws SQLException; + + int applicable(ResultSet resultSet, MapperConfig config) throws SQLException; + + int applicable(ResultSetMetaData meta) throws SQLException; + + int applicable(ResultSetMetaData meta, MapperConfig config) throws SQLException; + + default List types(){ + return Collections.emptyList(); + } +} diff --git a/sadu-mapper/src/main/java/de/chojo/sadu/mapper/rowmapper/RowMapper.java b/sadu-mapper/src/main/java/de/chojo/sadu/mapper/rowmapper/RowMapper.java index cf2e970e..00b161d2 100644 --- a/sadu-mapper/src/main/java/de/chojo/sadu/mapper/rowmapper/RowMapper.java +++ b/sadu-mapper/src/main/java/de/chojo/sadu/mapper/rowmapper/RowMapper.java @@ -28,7 +28,7 @@ * * @param type of returned object */ -public class RowMapper implements RowMapping { +public class RowMapper implements IRowMapper { private static final Logger log = getLogger(RowMapper.class); private final Class clazz; private final RowMapping mapper; @@ -61,12 +61,14 @@ public T map(Row row) throws SQLException { return mapper.map(row); } + @Override public T map(Row row, int index) throws SQLException { if(indexMapper == null) throw new UnsupportedOperationException("IndexMapper not set"); return indexMapper.apply(row, index); } + @Override public boolean isWildcard() { return columns.isEmpty(); } @@ -77,6 +79,7 @@ public boolean isWildcard() { * @param resultSet result set * @return If the result set is not applicable 0 will be returned. Otherwise, the count of applicable rows will be returned. */ + @Override public int applicable(ResultSet resultSet) throws SQLException { return applicable(resultSet, MapperConfig.DEFAULT); } @@ -87,6 +90,7 @@ public int applicable(ResultSet resultSet) throws SQLException { * @param resultSet result set * @return If the result set is not applicable 0 will be returned. Otherwise, the count of applicable rows will be returned. */ + @Override public int applicable(ResultSet resultSet, MapperConfig config) throws SQLException { return applicable(resultSet.getMetaData(), config); } @@ -97,6 +101,7 @@ public int applicable(ResultSet resultSet, MapperConfig config) throws SQLExcept * @param meta meta of a result set * @return If the result set is not applicable 0 will be returned. Otherwise, the count of applicable rows will be returned. */ + @Override public int applicable(ResultSetMetaData meta) { return applicable(meta, MapperConfig.DEFAULT); } @@ -108,6 +113,7 @@ public int applicable(ResultSetMetaData meta) { * @param config mapper config * @return If the result set is not applicable 0 will be returned. Otherwise, the count of applicable rows will be returned. */ + @Override public int applicable(ResultSetMetaData meta, MapperConfig config) { Set names; try { @@ -145,6 +151,7 @@ public int applicable(ResultSetMetaData meta, MapperConfig config) { return overlap.size(); } + @Override public List types() { return Collections.unmodifiableList(types); } diff --git a/sadu-mapper/src/main/java/de/chojo/sadu/mapper/rowmapper/RowMapperBuilder.java b/sadu-mapper/src/main/java/de/chojo/sadu/mapper/rowmapper/RowMapperBuilder.java index de1186e6..a1eeae6d 100644 --- a/sadu-mapper/src/main/java/de/chojo/sadu/mapper/rowmapper/RowMapperBuilder.java +++ b/sadu-mapper/src/main/java/de/chojo/sadu/mapper/rowmapper/RowMapperBuilder.java @@ -11,8 +11,10 @@ import de.chojo.sadu.mapper.wrapper.Row; import java.sql.SQLException; +import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; /** @@ -24,7 +26,7 @@ public class RowMapperBuilder implements PartialRowMapper { private final Class clazz; private final Set columns = new HashSet<>(); private RowMapping mapper; - private List types; + private List types = Collections.emptyList(); private ThrowingBiFunction indexMapper; RowMapperBuilder(Class clazz) { @@ -69,7 +71,7 @@ public RowMapper build() { } public RowMapperBuilder types(List types) { - this.types = types; + this.types = Objects.requireNonNull(types); return this; } diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/configuration/ConnectedQueryConfiguration.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/configuration/ConnectedQueryConfiguration.java index bf8f4653..5d34f053 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/configuration/ConnectedQueryConfiguration.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/configuration/ConnectedQueryConfiguration.java @@ -6,6 +6,7 @@ package de.chojo.sadu.queries.configuration; +import de.chojo.sadu.mapper.IRowMapperRegistry; import de.chojo.sadu.mapper.RowMapperRegistry; import de.chojo.sadu.queries.exception.WrappedQueryExecutionException; import de.chojo.sadu.queries.query.QueryImpl; @@ -18,7 +19,7 @@ public class ConnectedQueryConfiguration extends QueryConfiguration implements AutoCloseable { private Connection connection = null; - ConnectedQueryConfiguration(QueryImpl query, DataSource dataSource, boolean atomic, boolean throwExceptions, Consumer exceptionHandler, RowMapperRegistry rowMapperRegistry) { + ConnectedQueryConfiguration(QueryImpl query, DataSource dataSource, boolean atomic, boolean throwExceptions, Consumer exceptionHandler, IRowMapperRegistry rowMapperRegistry) { super(query, dataSource, atomic, throwExceptions, exceptionHandler, rowMapperRegistry); } diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/configuration/QueryConfiguration.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/configuration/QueryConfiguration.java index 5c569e35..c4045e83 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/configuration/QueryConfiguration.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/configuration/QueryConfiguration.java @@ -6,6 +6,7 @@ package de.chojo.sadu.queries.configuration; +import de.chojo.sadu.mapper.IRowMapperRegistry; import de.chojo.sadu.mapper.RowMapperRegistry; import de.chojo.sadu.queries.api.query.ParsedQuery; import de.chojo.sadu.queries.api.query.Query; @@ -27,9 +28,9 @@ public class QueryConfiguration { protected final boolean atomic; protected final boolean throwExceptions; protected final Consumer exceptionHandler; - protected final RowMapperRegistry rowMapperRegistry; + protected final IRowMapperRegistry rowMapperRegistry; - QueryConfiguration(@NotNull DataSource dataSource, boolean atomic, boolean throwExceptions, Consumer exceptionHandler, RowMapperRegistry rowMapperRegistry) { + QueryConfiguration(@NotNull DataSource dataSource, boolean atomic, boolean throwExceptions, Consumer exceptionHandler, IRowMapperRegistry rowMapperRegistry) { query = null; this.dataSource = dataSource; this.atomic = atomic; @@ -38,7 +39,7 @@ public class QueryConfiguration { this.rowMapperRegistry = rowMapperRegistry; } - QueryConfiguration(QueryImpl query, @NotNull DataSource dataSource, boolean atomic, boolean throwExceptions, Consumer exceptionHandler, RowMapperRegistry rowMapperRegistry) { + QueryConfiguration(QueryImpl query, @NotNull DataSource dataSource, boolean atomic, boolean throwExceptions, Consumer exceptionHandler, IRowMapperRegistry rowMapperRegistry) { this.query = query; this.dataSource = dataSource; this.atomic = atomic; @@ -123,7 +124,7 @@ public boolean throwExceptions() { * * @return The {@link RowMapperRegistry} object from the QueryConfiguration. */ - public RowMapperRegistry rowMapperRegistry() { + public IRowMapperRegistry rowMapperRegistry() { return rowMapperRegistry; } diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/configuration/QueryConfigurationBuilder.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/configuration/QueryConfigurationBuilder.java index 1faa68d3..d1e6421d 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/configuration/QueryConfigurationBuilder.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/configuration/QueryConfigurationBuilder.java @@ -7,6 +7,7 @@ package de.chojo.sadu.queries.configuration; import de.chojo.sadu.core.exceptions.ExceptionTransformer; +import de.chojo.sadu.mapper.IRowMapperRegistry; import de.chojo.sadu.mapper.RowMapperRegistry; import org.jetbrains.annotations.NotNull; @@ -23,7 +24,7 @@ public class QueryConfigurationBuilder { System.err.println(ExceptionTransformer.prettyException(throwable)); throwable.printStackTrace(); }; - private RowMapperRegistry rowMapperRegistry = new RowMapperRegistry(); + private IRowMapperRegistry rowMapperRegistry = new RowMapperRegistry(); /** * QueryConfigurationBuilder is a builder class used to create an instance of QueryConfiguration. @@ -76,7 +77,7 @@ public QueryConfigurationBuilder setExceptionHandler(Consumer exce * @param rowMapperRegistry the RowMapperRegistry to set * @return the QueryConfigurationBuilder instance */ - public QueryConfigurationBuilder setRowMapperRegistry(RowMapperRegistry rowMapperRegistry) { + public QueryConfigurationBuilder setRowMapperRegistry(IRowMapperRegistry rowMapperRegistry) { this.rowMapperRegistry = rowMapperRegistry; return this; } diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/converter/StandardValueConverter.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/converter/StandardValueConverter.java index e508d837..8f75a11d 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/converter/StandardValueConverter.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/converter/StandardValueConverter.java @@ -1,3 +1,9 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + package de.chojo.sadu.queries.converter; import de.chojo.sadu.mapper.reader.StandardReader; diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/converter/ValueConverter.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/converter/ValueConverter.java index db03fa0e..ec139fa9 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/converter/ValueConverter.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/converter/ValueConverter.java @@ -1,3 +1,9 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + package de.chojo.sadu.queries.converter; import de.chojo.sadu.core.exceptions.ThrowingBiFunction; diff --git a/settings.gradle.kts b/settings.gradle.kts index fba40d18..619268c1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -43,6 +43,10 @@ dependencyResolutionManagement { version("slf4j", "2.0.13") library("slf4j-api", "org.slf4j", "slf4j-api").versionRef("slf4j") + + version("jackson", "2.17.1") + library("jackson-jsr310","com.fasterxml.jackson.datatype","jackson-datatype-jsr310").versionRef("jackson") + library("jackson-databind","com.fasterxml.jackson.core", "jackson-databind").versionRef("jackson") } create("testlibs") {