work on db connection basic
This commit is contained in:
parent
1142def290
commit
2fa76d84df
6
.idea/copilot.data.migration.agent.xml
generated
Normal file
6
.idea/copilot.data.migration.agent.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AgentMigrationStateService">
|
||||
<option name="migrationStatus" value="COMPLETED" />
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/copilot.data.migration.ask.xml
generated
Normal file
6
.idea/copilot.data.migration.ask.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AskMigrationStateService">
|
||||
<option name="migrationStatus" value="COMPLETED" />
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/copilot.data.migration.ask2agent.xml
generated
Normal file
6
.idea/copilot.data.migration.ask2agent.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Ask2AgentMigrationStateService">
|
||||
<option name="migrationStatus" value="COMPLETED" />
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/copilot.data.migration.edit.xml
generated
Normal file
6
.idea/copilot.data.migration.edit.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EditMigrationStateService">
|
||||
<option name="migrationStatus" value="COMPLETED" />
|
||||
</component>
|
||||
</project>
|
||||
16
.idea/kotlinc.xml
generated
Normal file
16
.idea/kotlinc.xml
generated
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Kotlin2JsCompilerArguments">
|
||||
<option name="moduleKind" value="plain" />
|
||||
</component>
|
||||
<component name="Kotlin2JvmCompilerArguments">
|
||||
<option name="jvmTarget" value="1.8" />
|
||||
</component>
|
||||
<component name="KotlinCommonCompilerArguments">
|
||||
<option name="apiVersion" value="2.1" />
|
||||
<option name="languageVersion" value="2.1" />
|
||||
</component>
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="2.2.0" />
|
||||
</component>
|
||||
</project>
|
||||
95
pom.xml
95
pom.xml
@ -12,6 +12,7 @@
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<kotlin.version>2.2.0</kotlin.version>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
@ -24,6 +25,70 @@
|
||||
<target>21</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>compile</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sourceDirs>
|
||||
<source>src/main/java</source>
|
||||
<source>target/generated-sources/annotations</source>
|
||||
</sourceDirs>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test-compile</id>
|
||||
<phase>test-compile</phase>
|
||||
<goals>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sourceDirs>
|
||||
<source>src/test/java</source>
|
||||
<source>target/generated-test-sources/test-annotations</source>
|
||||
</sourceDirs>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<jvmTarget>1.8</jvmTarget>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-compile</id>
|
||||
<phase>none</phase>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>default-testCompile</id>
|
||||
<phase>none</phase>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>compile</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>testCompile</id>
|
||||
<phase>test-compile</phase>
|
||||
<goals>
|
||||
<goal>testCompile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
@ -69,6 +134,17 @@
|
||||
<version>2.0.16</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-scripting-jvm</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-scripting-common</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- TEST -->
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
|
||||
@ -78,5 +154,24 @@
|
||||
<version>5.13.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>2.3.230</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib-jdk8</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-test</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@ -22,6 +22,7 @@ public class App {
|
||||
.build();
|
||||
|
||||
db.init();
|
||||
Migration.of(db).getPendingBaseMigrations().forEach(f -> System.out.println(f.getName()));
|
||||
|
||||
var app = Javalin.create(cnf -> {});
|
||||
app.before(
|
||||
|
||||
@ -2,63 +2,95 @@ package dev.mduchene;
|
||||
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.jooq.impl.SQLDataType;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.conf.RenderQuotedNames;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.SQLDialect;
|
||||
|
||||
public class Db {
|
||||
private HikariDataSource dataSource;
|
||||
private Db() {}
|
||||
private HikariDataSource dataSource;
|
||||
private org.jooq.DSLContext dsl;
|
||||
|
||||
public void init() {
|
||||
private Db() {}
|
||||
|
||||
public void init() {
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
connection.setAutoCommit(true);
|
||||
} catch (Exception e) {
|
||||
// Ignore if the table already exists
|
||||
}
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private String url;
|
||||
private String user;
|
||||
private String password;
|
||||
|
||||
private Builder() {}
|
||||
|
||||
public static Builder create() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private String url;
|
||||
private String user;
|
||||
private String password;
|
||||
|
||||
private Builder() {}
|
||||
public static Builder create() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public Builder url(String url) {
|
||||
this.url = url;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder user(String user) {
|
||||
this.user = user;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder password(String password) {
|
||||
this.password = password;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Db build() {
|
||||
Db db = new Db();
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setJdbcUrl(url);
|
||||
config.setUsername(user);
|
||||
config.setPassword(password);
|
||||
config.addDataSourceProperty("cachePrepStmts", "true");
|
||||
config.addDataSourceProperty("prepStmtCacheSize", "250");
|
||||
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
|
||||
config.setMaximumPoolSize(64);
|
||||
db.dataSource = new HikariDataSource(config);
|
||||
return db;
|
||||
}
|
||||
public Builder url(String url) {
|
||||
this.url = url;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Connection getConnection() throws Exception {
|
||||
Connection connection = dataSource.getConnection();
|
||||
connection.setAutoCommit(false);
|
||||
return connection;
|
||||
public Builder user(String user) {
|
||||
this.user = user;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder password(String password) {
|
||||
this.password = password;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Db build() {
|
||||
Db db = new Db();
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setJdbcUrl(url);
|
||||
config.setUsername(user);
|
||||
config.setPassword(password);
|
||||
config.addDataSourceProperty("cachePrepStmts", "true");
|
||||
config.addDataSourceProperty("prepStmtCacheSize", "250");
|
||||
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
|
||||
config.setMaximumPoolSize(64);
|
||||
db.dataSource = new HikariDataSource(config);
|
||||
db.dsl =
|
||||
DSL.using(
|
||||
db.dataSource,
|
||||
SQLDialect.MARIADB,
|
||||
new Settings().withRenderQuotedNames(RenderQuotedNames.NEVER));
|
||||
return db;
|
||||
}
|
||||
}
|
||||
|
||||
public Connection getConnection() throws Exception {
|
||||
Connection connection = dataSource.getConnection();
|
||||
connection.setAutoCommit(false);
|
||||
return connection;
|
||||
}
|
||||
|
||||
public void run(String query) {
|
||||
try (Connection connection = getConnection()) {
|
||||
dsl.execute(query);
|
||||
connection.commit();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
public DSLContext dsl() {
|
||||
return dsl;
|
||||
}
|
||||
}
|
||||
|
||||
77
src/main/java/dev/mduchene/Migration.java
Normal file
77
src/main/java/dev/mduchene/Migration.java
Normal file
@ -0,0 +1,77 @@
|
||||
package dev.mduchene;
|
||||
|
||||
import org.jooq.Meta;
|
||||
import org.jooq.impl.DSL;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.sql.Connection;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Migration {
|
||||
|
||||
private final Db db;
|
||||
|
||||
private Migration(Db db) {
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
public static Migration of(Db db) {
|
||||
return new Migration(db);
|
||||
}
|
||||
|
||||
public List<File> getPendingBaseMigrations() {
|
||||
List<String> ranMigrations = getRanBaseMigrations();
|
||||
List<File> migrations = ResourceFileLister.listFilesInResourceFolder("migrations");
|
||||
return migrations.stream()
|
||||
.filter(file -> !ranMigrations.contains(file.getName()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public boolean tableExists(String tableName) {
|
||||
// Get the Meta object, which contains all database metadata
|
||||
Meta meta = db.dsl().meta();
|
||||
|
||||
// Use the getTables() method with a filter
|
||||
return meta.getTables(DSL.name("bolts", tableName)).stream()
|
||||
.anyMatch(
|
||||
table ->
|
||||
table.getName().equalsIgnoreCase(tableName)
|
||||
&& table.getSchema().getName().equalsIgnoreCase("bolts"));
|
||||
}
|
||||
|
||||
public List<String> getRanBaseMigrations() {
|
||||
try (Connection connection = db.getConnection()) {
|
||||
boolean migrationsExists = tableExists("_migrations");
|
||||
if (!migrationsExists) return List.of();
|
||||
|
||||
return db.dsl()
|
||||
.select(DSL.field("name"))
|
||||
.from(DSL.table("_migrations"))
|
||||
.where(DSL.field("base").eq(true))
|
||||
.and(DSL.field("executedAt").isNull())
|
||||
.fetch(DSL.field("name"), String.class);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getRanMigrations() {
|
||||
try (Connection connection = db.getConnection()) {
|
||||
return db.dsl()
|
||||
.select(DSL.field("name"))
|
||||
.from(DSL.table("_migrations"))
|
||||
.fetch(DSL.field("name"), String.class);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
37
src/main/java/dev/mduchene/ResourceFileLister.java
Normal file
37
src/main/java/dev/mduchene/ResourceFileLister.java
Normal file
@ -0,0 +1,37 @@
|
||||
package dev.mduchene;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ResourceFileLister {
|
||||
|
||||
public static void main(String[] args) {
|
||||
listFilesInResourceFolder("data");
|
||||
}
|
||||
|
||||
public static List<File> listFilesInResourceFolder(String folderName) {
|
||||
ClassLoader classLoader = ResourceFileLister.class.getClassLoader();
|
||||
URL folderUrl = classLoader.getResource(folderName);
|
||||
|
||||
if (folderUrl == null) {
|
||||
throw new IllegalArgumentException("Folder not found: " + folderName);
|
||||
}
|
||||
|
||||
try {
|
||||
Path folderPath = Paths.get(folderUrl.toURI());
|
||||
try (Stream<Path> stream = Files.list(folderPath)) {
|
||||
return stream.filter(Files::isRegularFile).map(Path::toFile).toList();
|
||||
}
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user