From ee6c6eda02e6bcb78ee1f5431414628452b0b9fd Mon Sep 17 00:00:00 2001 From: Piotr Dec Date: Tue, 21 May 2024 22:40:44 +0200 Subject: [PATCH] feat: Database model & configuration --- pom.xml | 21 ++++++++ src/main/java/eu/ztsh/wymiana/Main.java | 4 ++ .../data/config/DatabaseConfiguration.java | 54 +++++++++++++++++++ .../wymiana/data/config/HsqlDbProperties.java | 8 +++ .../wymiana/data/entity/CurrencyEntity.java | 23 ++++++++ .../ztsh/wymiana/data/entity/UserEntity.java | 29 ++++++++++ .../data/repository/UserRepository.java | 8 +++ src/main/resources/application.yaml | 13 +++++ src/test/java/.gitkeep | 0 .../data/repository/UserRepositoryTest.java | 49 +++++++++++++++++ 10 files changed, 209 insertions(+) create mode 100644 src/main/java/eu/ztsh/wymiana/data/config/DatabaseConfiguration.java create mode 100644 src/main/java/eu/ztsh/wymiana/data/config/HsqlDbProperties.java create mode 100644 src/main/java/eu/ztsh/wymiana/data/entity/CurrencyEntity.java create mode 100644 src/main/java/eu/ztsh/wymiana/data/entity/UserEntity.java create mode 100644 src/main/java/eu/ztsh/wymiana/data/repository/UserRepository.java delete mode 100644 src/test/java/.gitkeep create mode 100644 src/test/java/eu/ztsh/wymiana/data/repository/UserRepositoryTest.java diff --git a/pom.xml b/pom.xml index 61c5e3b..622e927 100644 --- a/pom.xml +++ b/pom.xml @@ -41,8 +41,29 @@ org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-data-jpa + + + + + org.projectlombok + lombok + provided + + + + + org.hsqldb + hsqldb + + + org.springframework.boot + spring-boot-starter-test + org.junit.jupiter junit-jupiter diff --git a/src/main/java/eu/ztsh/wymiana/Main.java b/src/main/java/eu/ztsh/wymiana/Main.java index 7687607..c6e067d 100644 --- a/src/main/java/eu/ztsh/wymiana/Main.java +++ b/src/main/java/eu/ztsh/wymiana/Main.java @@ -2,8 +2,12 @@ package eu.ztsh.wymiana; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; +import org.springframework.boot.context.properties.EnableConfigurationProperties; @SpringBootApplication +@EnableConfigurationProperties +@ConfigurationPropertiesScan public class Main { public static void main(String[] args) { diff --git a/src/main/java/eu/ztsh/wymiana/data/config/DatabaseConfiguration.java b/src/main/java/eu/ztsh/wymiana/data/config/DatabaseConfiguration.java new file mode 100644 index 0000000..64ed335 --- /dev/null +++ b/src/main/java/eu/ztsh/wymiana/data/config/DatabaseConfiguration.java @@ -0,0 +1,54 @@ +package eu.ztsh.wymiana.data.config; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import org.hsqldb.persist.HsqlProperties; +import org.hsqldb.server.Server; +import org.hsqldb.server.ServerAcl; +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.io.IOException; + +@Configuration +public class DatabaseConfiguration { + + /** + * Create HSQL Database instance that is accessible from outside of application + * + * @return server instance + * @throws ServerAcl.AclFormatException when instantiating ServerAcl + * @throws IOException when instantiating ServerAcl + */ + @Bean + public Server hsqlServer(HsqlDbProperties properties) throws ServerAcl.AclFormatException, IOException { + var server = new Server(); + var props = new HsqlProperties(); + props.setProperty("server.database.0", String.format("mem:%s", properties.name())); + props.setProperty("server.dbname.0", properties.name()); + props.setProperty("server.no_system_exit", true); + props.setProperty("server.port", properties.port()); + server.setProperties(props); + server.start(); + return server; + } + + /** + * As we manually create database instance, we need also create datasource instance. + * HSQL instance is passed to force spring to create {@link Server} before pool. + * + * @param dataSourceProperties spring.datasource.* properties + * @return datasource instance + */ + @Bean + public HikariDataSource hikariDataSource(DataSourceProperties dataSourceProperties, Server ignore) { + var config = new HikariConfig(); + config.setJdbcUrl(dataSourceProperties.getUrl()); + config.setUsername(dataSourceProperties.getUsername()); + config.setPassword(dataSourceProperties.getPassword()); + config.setDriverClassName(dataSourceProperties.getDriverClassName()); + return new HikariDataSource(config); + } + +} diff --git a/src/main/java/eu/ztsh/wymiana/data/config/HsqlDbProperties.java b/src/main/java/eu/ztsh/wymiana/data/config/HsqlDbProperties.java new file mode 100644 index 0000000..b510225 --- /dev/null +++ b/src/main/java/eu/ztsh/wymiana/data/config/HsqlDbProperties.java @@ -0,0 +1,8 @@ +package eu.ztsh.wymiana.data.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties("hsqldb") +public record HsqlDbProperties(String name, int port) { + +} diff --git a/src/main/java/eu/ztsh/wymiana/data/entity/CurrencyEntity.java b/src/main/java/eu/ztsh/wymiana/data/entity/CurrencyEntity.java new file mode 100644 index 0000000..441b224 --- /dev/null +++ b/src/main/java/eu/ztsh/wymiana/data/entity/CurrencyEntity.java @@ -0,0 +1,23 @@ +package eu.ztsh.wymiana.data.entity; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "currency") +public class CurrencyEntity { + + @Id + String pesel; + @Id + String symbol; + Double amount; + +} diff --git a/src/main/java/eu/ztsh/wymiana/data/entity/UserEntity.java b/src/main/java/eu/ztsh/wymiana/data/entity/UserEntity.java new file mode 100644 index 0000000..a77e3c7 --- /dev/null +++ b/src/main/java/eu/ztsh/wymiana/data/entity/UserEntity.java @@ -0,0 +1,29 @@ +package eu.ztsh.wymiana.data.entity; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "user") +public class UserEntity { + + @Id + String pesel; + String name; + String surname; + + @OneToMany(cascade = CascadeType.ALL, mappedBy = "pesel") + List currencies; + +} diff --git a/src/main/java/eu/ztsh/wymiana/data/repository/UserRepository.java b/src/main/java/eu/ztsh/wymiana/data/repository/UserRepository.java new file mode 100644 index 0000000..e77f9e9 --- /dev/null +++ b/src/main/java/eu/ztsh/wymiana/data/repository/UserRepository.java @@ -0,0 +1,8 @@ +package eu.ztsh.wymiana.data.repository; + +import eu.ztsh.wymiana.data.entity.UserEntity; +import org.springframework.data.repository.CrudRepository; + +public interface UserRepository extends CrudRepository { + +} diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index e69de29..ae6306d 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -0,0 +1,13 @@ +hsqldb: + name: db + port: 9090 + +spring: + datasource: + username: sa + password: + url: jdbc:hsqldb:hsql://localhost:${hsqldb.port}/${hsqldb.name} + driver-class-name: org.hsqldb.jdbc.JDBCDriver + jpa: + hibernate: + ddl-auto: create diff --git a/src/test/java/.gitkeep b/src/test/java/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/java/eu/ztsh/wymiana/data/repository/UserRepositoryTest.java b/src/test/java/eu/ztsh/wymiana/data/repository/UserRepositoryTest.java new file mode 100644 index 0000000..1da3e81 --- /dev/null +++ b/src/test/java/eu/ztsh/wymiana/data/repository/UserRepositoryTest.java @@ -0,0 +1,49 @@ +package eu.ztsh.wymiana.data.repository; + +import eu.ztsh.wymiana.data.entity.CurrencyEntity; +import eu.ztsh.wymiana.data.entity.UserEntity; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest +@ExtendWith(SpringExtension.class) +class UserRepositoryTest { + + private final UserRepository userRepository; + + @Autowired + UserRepositoryTest(UserRepository userRepository) { + this.userRepository = userRepository; + } + + @BeforeEach + void prepareTest() { + userRepository.deleteAll(); + } + + @Test + @Transactional + @DisplayName("Basic insert & get test") + void basicTest() { + var pesel = "00281018264"; + var entity = new UserEntity(pesel, "Janina", "Kowalska", + List.of(new CurrencyEntity(pesel, "PLN", 20.10))); + userRepository.save(entity); + assertThat(userRepository.findById(pesel)) + .isNotEmpty() + .get() + .usingRecursiveComparison() + .isEqualTo(entity); + } + +}