added db handler
~6h work
This commit is contained in:
parent
fad46df96c
commit
ad335a545a
@ -1,6 +1,5 @@
|
|||||||
package at.nanopenguin.mtcg.application.service;
|
package at.nanopenguin.mtcg.application.service;
|
||||||
|
|
||||||
import at.nanopenguin.mtcg.application.service.schemas.UserCredentials;
|
|
||||||
import at.nanopenguin.mtcg.http.HttpMethod;
|
import at.nanopenguin.mtcg.http.HttpMethod;
|
||||||
import at.nanopenguin.mtcg.http.HttpRequest;
|
import at.nanopenguin.mtcg.http.HttpRequest;
|
||||||
import at.nanopenguin.mtcg.http.HttpStatus;
|
import at.nanopenguin.mtcg.http.HttpStatus;
|
||||||
|
|||||||
@ -1,11 +1,7 @@
|
|||||||
package at.nanopenguin.mtcg.application.service.schemas;
|
package at.nanopenguin.mtcg.application.service.schemas;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
|
||||||
|
|
||||||
@JsonSerialize
|
|
||||||
@JsonDeserialize
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public record Card(String id, String name, Float damage) {
|
public record Card(String id, String name, Float damage) {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,7 @@
|
|||||||
package at.nanopenguin.mtcg.application.service.schemas;
|
package at.nanopenguin.mtcg.application.service.schemas;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
|
||||||
|
|
||||||
@JsonSerialize
|
|
||||||
@JsonDeserialize
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public record TradingDeal(String id, String cardToTrade, String type, Float minimumDamage) {
|
public record TradingDeal(String id, String cardToTrade, String type, Float minimumDamage) {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,7 @@
|
|||||||
package at.nanopenguin.mtcg.application.service.schemas;
|
package at.nanopenguin.mtcg.application.service.schemas;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
|
||||||
|
|
||||||
@JsonSerialize
|
|
||||||
@JsonDeserialize
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public record UserCredentials(String username, String password) {
|
public record UserCredentials(String username, String password) {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,7 @@
|
|||||||
package at.nanopenguin.mtcg.application.service.schemas;
|
package at.nanopenguin.mtcg.application.service.schemas;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
|
||||||
|
|
||||||
@JsonSerialize
|
|
||||||
@JsonDeserialize
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public record UserData(String name, String bio, String image) {
|
public record UserData(String name, String bio, String image) {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,7 @@
|
|||||||
package at.nanopenguin.mtcg.application.service.schemas;
|
package at.nanopenguin.mtcg.application.service.schemas;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
|
||||||
|
|
||||||
@JsonSerialize
|
|
||||||
@JsonDeserialize
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public record UserStats(String name, Integer elo, Integer wins, Integer losses) {
|
public record UserStats(String name, Integer elo, Integer wins, Integer losses) {
|
||||||
}
|
}
|
||||||
|
|||||||
138
src/at/nanopenguin/mtcg/db/DbQuery.java
Normal file
138
src/at/nanopenguin/mtcg/db/DbQuery.java
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
package at.nanopenguin.mtcg.db;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.Singular;
|
||||||
|
import lombok.val;
|
||||||
|
|
||||||
|
import java.sql.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
public final class DbQuery {
|
||||||
|
private static final String connectionString = "jdbc:postgres://localhost:5432/mydb?user=postgres&password=postgres";
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private final SqlCommand command;
|
||||||
|
@NonNull
|
||||||
|
private final Table table;
|
||||||
|
@Singular
|
||||||
|
private List<String> columns;
|
||||||
|
@Singular
|
||||||
|
private SortedMap<String, Object> parameters;
|
||||||
|
@Singular
|
||||||
|
private SortedMap<String, Object> conditions;
|
||||||
|
|
||||||
|
public static class DbQueryBuilder {
|
||||||
|
public ResultSet executeQuery() throws SQLException {
|
||||||
|
DbQuery dbQuery = this.build();
|
||||||
|
if (dbQuery.command != SqlCommand.SELECT) throw new SQLException();
|
||||||
|
return dbQuery.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int executeUpdate() throws SQLException {
|
||||||
|
DbQuery dbQuery = this.build();
|
||||||
|
return switch (dbQuery.command) {
|
||||||
|
case INSERT -> dbQuery.create();
|
||||||
|
case UPDATE -> dbQuery.update();
|
||||||
|
case DELETE -> dbQuery.delete();
|
||||||
|
default -> throw new SQLException();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Connection connect() throws SQLException {
|
||||||
|
return DriverManager.getConnection(connectionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildParameterizedString(@NonNull SortedMap<String, Object> parameters) {
|
||||||
|
if (!parameters.isEmpty()) {
|
||||||
|
return String.join(" = ?, ", parameters.keySet()) + " = ?";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private int create() throws SQLException {
|
||||||
|
if (this.parameters.isEmpty()) throw new SQLException("No parameters provided for INSERT statement.");
|
||||||
|
|
||||||
|
try (Connection connection = connect()) {
|
||||||
|
String columns = this.parameters.keySet().stream()
|
||||||
|
.filter(columnName -> columnName.matches("[a-zA-Z0-9_]+"))
|
||||||
|
.collect(Collectors.joining(", "));
|
||||||
|
|
||||||
|
String sql = String.format("INSERT INTO %s (%s) VALUES (%s);", table.table, columns, String.join(", ", Collections.nCopies(this.parameters.size(), "?")));
|
||||||
|
|
||||||
|
try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
|
||||||
|
int i = 1;
|
||||||
|
for (val entry : this.parameters.entrySet()) {
|
||||||
|
preparedStatement.setObject(i++, entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return preparedStatement.executeUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultSet read() throws SQLException {
|
||||||
|
try (Connection connection = connect()) {
|
||||||
|
StringJoiner columnJoiner = new StringJoiner(", ");
|
||||||
|
if (this.columns.isEmpty()) {
|
||||||
|
columnJoiner.add("*");
|
||||||
|
}
|
||||||
|
this.columns.forEach(columnJoiner::add);
|
||||||
|
|
||||||
|
String sql = String.format("SELECT %s FROM %s%s;", columnJoiner, table.table,
|
||||||
|
this.conditions.isEmpty() ? "" : " WHERE (" + this.buildParameterizedString(this.conditions) + ")");
|
||||||
|
|
||||||
|
try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
|
||||||
|
int i = 1;
|
||||||
|
for (val entry : this.conditions.entrySet()) {
|
||||||
|
preparedStatement.setObject(i++, entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return preparedStatement.executeQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int update() throws SQLException {
|
||||||
|
if (this.parameters.isEmpty()) throw new SQLException();
|
||||||
|
if (this.conditions.isEmpty()) throw new SQLException();
|
||||||
|
|
||||||
|
try (Connection connection = connect()) {
|
||||||
|
String sql = String.format("UPDATE %s SET %s WHERE (%s);", table.table,
|
||||||
|
this.buildParameterizedString(this.parameters),
|
||||||
|
this.buildParameterizedString(this.conditions));
|
||||||
|
|
||||||
|
PreparedStatement preparedStatement = connection.prepareStatement(sql);
|
||||||
|
|
||||||
|
int i = 1;
|
||||||
|
for (val entry : this.parameters.entrySet()) {
|
||||||
|
preparedStatement.setObject(i++, entry.getValue());
|
||||||
|
}
|
||||||
|
for (val entry : this.conditions.entrySet()) {
|
||||||
|
preparedStatement.setObject(i++, entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return preparedStatement.executeUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int delete() throws SQLException {
|
||||||
|
if (this.conditions.isEmpty()) throw new SQLException();
|
||||||
|
try (Connection connection = connect()) {
|
||||||
|
|
||||||
|
String sql = String.format("DELETE FROM %s WHERE (%s);", table.table, this.buildParameterizedString(this.conditions));
|
||||||
|
|
||||||
|
try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
|
||||||
|
int i = 1;
|
||||||
|
for (val entry : this.conditions.entrySet()) {
|
||||||
|
preparedStatement.setObject(i++, entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return preparedStatement.executeUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/at/nanopenguin/mtcg/db/SqlCommand.java
Normal file
8
src/at/nanopenguin/mtcg/db/SqlCommand.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package at.nanopenguin.mtcg.db;
|
||||||
|
|
||||||
|
public enum SqlCommand {
|
||||||
|
INSERT,
|
||||||
|
SELECT,
|
||||||
|
UPDATE,
|
||||||
|
DELETE,
|
||||||
|
}
|
||||||
10
src/at/nanopenguin/mtcg/db/Table.java
Normal file
10
src/at/nanopenguin/mtcg/db/Table.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package at.nanopenguin.mtcg.db;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum Table {
|
||||||
|
USERS("users");
|
||||||
|
|
||||||
|
public final String table;
|
||||||
|
}
|
||||||
@ -1,5 +1,8 @@
|
|||||||
package at.nanopenguin.mtcg.http;
|
package at.nanopenguin.mtcg.http;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
public enum HttpStatus {
|
public enum HttpStatus {
|
||||||
OK(200, "OK"),
|
OK(200, "OK"),
|
||||||
CREATED(201, "Created"),
|
CREATED(201, "Created"),
|
||||||
@ -15,9 +18,4 @@ public enum HttpStatus {
|
|||||||
|
|
||||||
public final int statusCode;
|
public final int statusCode;
|
||||||
public final String statusMessage;
|
public final String statusMessage;
|
||||||
|
|
||||||
HttpStatus(int code, String message) {
|
|
||||||
this.statusCode = code;
|
|
||||||
this.statusMessage = message;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package at.nanopenguin.mtcg.http;
|
|||||||
|
|
||||||
import at.nanopenguin.mtcg.application.service.Service;
|
import at.nanopenguin.mtcg.application.service.Service;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -9,15 +10,11 @@ import java.io.InputStreamReader;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class RequestHandler implements Runnable {
|
public class RequestHandler implements Runnable {
|
||||||
private final Socket serviceSocket;
|
private final Socket serviceSocket;
|
||||||
private final Router router;
|
private final Router router;
|
||||||
|
|
||||||
public RequestHandler(Socket serviceSocket, Router router) {
|
|
||||||
this.serviceSocket = serviceSocket;
|
|
||||||
this.router = router;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -1,22 +1,19 @@
|
|||||||
package at.nanopenguin.mtcg.http;
|
package at.nanopenguin.mtcg.http;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class Server {
|
public class Server {
|
||||||
private final int port; // 16-bit unsigned, not enforced
|
private final int port; // 16-bit unsigned, not enforced
|
||||||
private final int threads;
|
private final int threads;
|
||||||
private final Router router;
|
private final Router router;
|
||||||
|
|
||||||
public Server(int port, int threads, Router router) {
|
|
||||||
this.port = port;
|
|
||||||
this.threads = threads;
|
|
||||||
this.router = router;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start() throws IOException {
|
public void start() throws IOException {
|
||||||
try (ServerSocket listener = new ServerSocket(this.port)) {
|
try (ServerSocket listener = new ServerSocket(this.port)) {
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user