Äquivalent zu Django Models in Java

MJannek

Bekanntes Mitglied
Ich möchte in Java auf meine MySQL Datenbank zugreifen. Das funktioniert auch sehr gut. Ich möchte jedoch für jede Tabelle eine eigene Klasse erstellen. Die Attribute dieser Klassen sollen die Spalten der jeweiligen Tabelle widerspiegeln. Außerdem sollen Änderungen in den Klassendefinitionen automatisch in die Datenbank übertragen werden.

Ich möchte dann beispielsweise folgendes aufzurufen um aus der DB zu lesen:
Java:
User currentUser = User.getAllObjects().filter(User.id = 1);

Ich weiß, dass soetwas in Python existiert. Dort sind es die Django Models. Jedoch möchte ich soetwas in Java haben. Außerdem weiß ich, dass Frameworks wie Hibernate und Spring/ Spring Boot existiert.

Jedoch weiß ich nicht was sich dort am besten eignet. Meine Anwendung läuft lokal und soll keine Web-Entwicklung, falls diese Information notwendig ist.
Für Tipps und Hinweise bin ich offen.
Vielen Dank
LG Markus
 

KonradN

Super-Moderator
Mitarbeiter
Wir können Dir nicht sagen, was für Dich das Beste ist. Dafür wissen wir doch viel zu wenig.

Ich würde zu Hibernate raten. Das dürfte die breiteste Community haben und ist eine JPA Implementierung.
Alternativen dazu wären dann JPA Implementationen wie EclipeLink oder OpenJPA.

Der Vorteil ist, dass Du damit dann die Java Persistence API nutzt, was ein guter Einstieg sein kann.

Alternativen wie MyBatis (SQL Mapper) oder JOOQ ("SQL First") sind natürlich auch interessant, vor allem, wenn man volle Transparenz bezüglich SQL haben möchte oder man sehr komplexe Abfragen benötigt.
 

MJannek

Bekanntes Mitglied
XML:
plugins {
    id("java")
    id("org.hibernate.orm") version "5.4.12.Final"
}

group = "org.mjannek"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
    gradlePluginPortal()
}

dependencies {
    implementation("org.hibernate:hibernate-core:5.+")
    implementation("mysql:mysql-connector-java:8.+")
    implementation("javax.persistence:javax.persistence-api:2.2")
    implementation("org.jsoup:jsoup:1.18.3")
    implementation("com.sun.mail:javax.mail")
    testImplementation(platform("org.junit:junit-bom:5.10.0"))
    testImplementation("org.junit.jupiter:junit-jupiter")
}

tasks.test {
    useJUnitPlatform()
}

tasks.register("hibernateReverseEngineering", JavaExec) {
    mainClass = "org.hibernate.tool.ant.HibernateToolTask"
    classpath = sourceSets.main.runtimeClasspath

    jvmArgs = ['-Dhibernate.tool.hbm2ddl.auto=update']
    args = [
        'reverse-engineer',
        '-configurationfile', 'src/main/resources/hibernate.cfg.xml',
        '-outputdir', 'src/main/java',
        '-package', 'org.mjannek.sport.buli.tables'
    ]
}

Das ist meine build.gradle.kts Datei, die in einem automatisch erzeugten Ordner liegt. Jedoch sind alle zeilen in tasks.register rot unterstrichen.
Ich habe eine Bestehende MySQL Datenbank und möchte mittels revers Engineering die entsprechendenden java Klassen erzeugen.
Ausserdem habe ich in "src/main/ressources" noch folgende Daten"
hibernate.cfg.xml
XML:
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <!-- JDBC-Datenbank-Verbindungseinstellungen -->
        <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://servername/schema</property>
        <property name="hibernate.connection.username">username</property>
        <property name="hibernate.connection.password">pw</property>

        <!-- JDBC-Verbindungspool-Einstellungen -->
        <property name="hibernate.c3p0.min_size">5</property>
        <property name="hibernate.c3p0.max_size">20</property>
        <property name="hibernate.c3p0.timeout">300</property>
        <property name="hibernate.c3p0.max_statements">50</property>
        <property name="hibernate.c3p0.idle_test_period">3000</property>

        <!-- SQL-Dialect -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- Ausgeführte SQL-Anweisungen anzeigen -->
        <property name="hibernate.show_sql">true</property>

        <!-- Aktualisierung des Datenbankschemas -->
        <property name="hibernate.hbm2ddl.auto">update</property>

        <!-- Paket zum Scannen nach annotierten Entitäten -->
        <property name="hibernate.packagesToScan">root.to.package</property>
    </session-factory>
</hibernate-configuration>
hibernate.reveng.xml
XML:
<hibernate-reverse-engineering>
    <schema-selection match-schema="schema" />
    <table-filter match-name="*" />
</hibernate-reverse-engineering>
Wo ist mein Fehler?
 

MJannek

Bekanntes Mitglied
Ich habe hier eine HibernateUtilKlasse
Java:
package org.mjannek.database;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.reflections.Reflections;
import org.reflections.scanners.Scanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;

import javax.persistence.Entity;
import java.util.Set;

public class HibernateUtil {
    private static final SessionFactory sessionFactory;

    static {
        try {
            Configuration configuration = new Configuration();
            configuration.configure("hibernate.cfg.xml");

            // Erstelle eine Reflections-Konfiguration mit SubTypesScanner
            Reflections reflections = new Reflections(new ConfigurationBuilder()
                    .setUrls(ClasspathHelper.forPackage("org.mjannek.sport.buli.tables"))
                    .setScanners(Scanners.SubTypes, Scanners.TypesAnnotated)
            );

            // Suche nach allen annotierten Klassen im Paket org.mjannek.sport.buli.tables
            Set<Class<?>> annotatedClasses = reflections.getTypesAnnotatedWith(Entity.class);
            for (Class<?> clazz : annotatedClasses) {
                configuration.addAnnotatedClass(clazz);
            }

            sessionFactory = configuration.buildSessionFactory();
        } catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public static void shutdown() {
        // Schließe Caches und Verbindungspools
        getSessionFactory().close();
    }
}
XML:
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- JDBC Database connection settings -->
        <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://server/schema</property>
        <property name="hibernate.connection.username">user</property>
        <property name="hibernate.connection.password">pw</property>

        <!-- JDBC connection pool settings -->
        <property name="hibernate.c3p0.min_size">5</property>
        <property name="hibernate.c3p0.max_size">20</property>
        <property name="hibernate.c3p0.timeout">300</property>
        <property name="hibernate.c3p0.max_statements">50</property>
        <property name="hibernate.c3p0.idle_test_period">3000</property>

        <!-- Specify dialect -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="hibernate.show_sql">true</property>

        <!-- Drop and re-create the database schema on startup -->
        <property name="hibernate.hbm2ddl.auto">update</property>

        <!-- Automatic detection of annotated entities -->
        <property name="hibernate.archive.autodetection">class,hbm</property>
    </session-factory>
</hibernate-configuration>

Meine build.gradle
Code:
plugins {
    id("java")
}

group = "org.mjannek"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.hibernate:hibernate-core:5.+")
    implementation("org.reflections:reflections:0.9.12")
    implementation("mysql:mysql-connector-java:8.+")
    implementation("javax.persistence:javax.persistence-api:2.2")
    implementation("org.jsoup:jsoup:1.18.3")
    implementation("com.sun.mail:javax.mail:1.6.2")
    testImplementation(platform("org.junit:junit-bom:5.10.0"))
    testImplementation("org.junit.jupiter:junit-jupiter")
}

tasks.test {
    useJUnitPlatform()
}


Folgende meine Entity Club
Java:
package org.mjannek.sport.buli.tables;

import javax.persistence.*;
import java.time.LocalDate;

@Entity
@Table(name = "clubs", uniqueConstraints = {
        @UniqueConstraint(columnNames = "link"),
        @UniqueConstraint(columnNames = "longname")
})
public class Club {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "longname", nullable = false, length = 255)
    private String longname;

    @Column(name = "shortname", nullable = false, length = 3)
    private String shortname;

    @Column(name = "foreground", length = 7)
    private String foreground;

    @Column(name = "background", length = 7)
    private String background;

    @Column(name = "foundingdate")
    private LocalDate foundingdate;

    @Column(name = "info", columnDefinition = "TEXT")
    private String info;

    @Column(name = "name", nullable = false, length = 255)
    private String name;

    @Column(name = "city", columnDefinition = "TEXT")
    private String city;

    @Column(name = "fullname", columnDefinition = "TEXT")
    private String fullname;

    @Column(name = "link", length = 255)
    private String link;

    // No-arg constructor for JPA
    public Club() {
    }

    // Constructor for setting id
    public Club(Long id) {
        this.id = id;
    }

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getLongname() {
        return longname;
    }

    public void setLongname(String longname) {
        this.longname = longname;
    }

    public String getShortname() {
        return shortname;
    }

    public void setShortname(String shortname) {
        this.shortname = shortname;
    }

    public String getForeground() {
        return foreground;
    }

    public void setForeground(String foreground) {
        this.foreground = foreground;
    }

    public String getBackground() {
        return background;
    }

    public void setBackground(String background) {
        this.background = background;
    }

    public LocalDate getFoundingdate() {
        return foundingdate;
    }

    public void setFoundingdate(LocalDate foundingdate) {
        this.foundingdate = foundingdate;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getFullname() {
        return fullname;
    }

    public void setFullname(String fullname) {
        this.fullname = fullname;
    }

    public String getLink() {
        return link;
    }

    public void setLink(String link) {
        this.link = link;
    }
}

Hier mein aufruf in der Main Klasse
Java:
package org.mjannek;

import org.hibernate.Session;
import org.mjannek.database.*;
import org.mjannek.sport.buli.tables.*;

public class Main {
    public static void main(String[] args) {
        // Öffne eine neue Session
        Session session = HibernateUtil.getSessionFactory().openSession();

        // Beginne eine Transaktion
        session.beginTransaction();

        // Beispiel zum Speichern eines Club-Objekts
        Club club = new Club();
        club.setLongname("Testverein");
        club.setShortname("TV");
        club.setLongname("Testverein 2024");
        // Setze andere Club-Attribute

        session.save(club);

        // Transaktion abschließen
        session.getTransaction().commit();

        // Session und SessionFactory schließen
        session.close();
        HibernateUtil.shutdown();
    }
}

Meine Fehlermeldungen:


Zum einen
Caused by: org.reflections.ReflectionsException: Scanner SubTypesScanner was not configured


zum anderen
Execution failed for task ':eek:rg.mjannek.Main.main()'.
Process 'command 'C:\Program Files\Java\jdk-23\bin\java.exe'' finished with non-zero exit value 1

* Try:
Run with --stacktrace option to get the stack trace.
Run with --info or --debug option to get more log output.
Run with --scan to get full insights.
Get more help at https://help.gradle.org.
BUILD FAILED in 23s
3 actionable tasks: 2 executed, 1 up-to-date

Vielen dank schonmal
 

MJannek

Bekanntes Mitglied
Java:
import org.reflections.Reflections;
import org.reflections.scanners.Scanners;

import javax.persistence.Entity;
import java.util.Set;

public class EntityFinder {
    public static void main(String[] args) {
        // Definiere das Package
        Reflections reflections = new Reflections("org.mjannek.sport.buli.tables", Scanners.TypesAnnotated);

        // Finde alle Klassen, die mit @Entity annotiert sind
        Set<Class<?>> entityClasses = reflections.getTypesAnnotatedWith(Entity.class);

        // Ausgabe der gefundenen Klassen
        entityClasses.forEach(System.out::println);
    }
}
Wo ist mein Fehler siehe Bild.

Code:
plugins {
    id("java")
}

group = "org.mjannek"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.hibernate:hibernate-core:5.+")
    implementation("org.reflections:reflections:0.9.12")
    implementation("mysql:mysql-connector-java:8.+")
    implementation("javax.persistence:javax.persistence-api:2.2")
    implementation("org.jsoup:jsoup:1.18.3")
    implementation("com.sun.mail:javax.mail:1.6.2")
    testImplementation(platform("org.junit:junit-bom:5.10.0"))
    testImplementation("org.junit.jupiter:junit-jupiter")
}

tasks.test {
    useJUnitPlatform()
}


Code:
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- JDBC Database connection settings -->
        <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://server:3306/schema</property>
        <property name="hibernate.connection.username">user</property>
        <property name="hibernate.connection.password">pw</property>

        <!-- JDBC connection pool settings -->
        <property name="hibernate.c3p0.min_size">5</property>
        <property name="hibernate.c3p0.max_size">20</property>
        <property name="hibernate.c3p0.timeout">300</property>
        <property name="hibernate.c3p0.max_statements">50</property>
        <property name="hibernate.c3p0.idle_test_period">3000</property>

        <!-- Specify dialect -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="hibernate.show_sql">true</property>

        <!-- Drop and re-create the database schema on startup -->
        <property name="hibernate.hbm2ddl.auto">update</property>

        <!-- Automatic detection of annotated entities -->
        <property name="hibernate.archive.autodetection">class,hbm</property>
    </session-factory>
</hibernate-configuration>
1735216045076.png
 

KonradN

Super-Moderator
Mitarbeiter
Weil Du eine alte Version eingebunden hast, bei der es noch keine enum Scanners gab.

Edit: Paar mehr Details: Du hast die Version 0.9.12. Auf Github kann man den Branch release/0913 ansehen:
Und siehe da - kein Scanners.

Generell sollte man sich seine Abhängigkeiten ansehen. So findet man bei https://github.com/ronmamo/reflections
❗ Please note: Reflections library is currently NOT under active development or maintenance ❗

Thank you for your continuous support!
There are open issues and also workarounds. Release version will be considered incase contributing PR fixing the main issues.

Last released org.reflections:reflections:0.10.2 (Oct 2021)

Ich würde also mindestens auf die aktuelle Version gehen. Aber wenn man sich das auf mvnrepositories ansieht:

Dann sieht man, dass man da auch Probleme mit Abhängigkeiten hat:
Vulnerabilities from dependencies:
CVE-2022-25647
Man kann hier also ggf. schauen, ob man das gson in der aktuellen Version unterschieben kann und sich die Schwachstelle anschauen, ob das Sinn macht / notwendig ist.
 
Zuletzt bearbeitet:

MJannek

Bekanntes Mitglied
Ich habe es jetzt himbekommen, Tabellen zu erstellen, jedoch werden Änderung nicht übernommen, wenn ich die Klassendefinitionen anpasse
Ich habe Club wie folgt, initial definiert:
Java:
package org.mjannek.sport.buli.tables;

import javax.persistence.*;
import java.time.LocalDate;

@Entity
@Table(name = "clubs", uniqueConstraints = {
        @UniqueConstraint(columnNames = "link"),
        @UniqueConstraint(columnNames = "longname")
})
public class Club {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(name = "longname", nullable = false, length = 255)
    private String longname;

    @Column(name = "shortname", nullable = false, length = 3)
    private String shortname;

    @Column(name = "foreground", length = 7)
    private String foreground;

    @Column(name = "background", length = 7)
    private String background;

    @Column(name = "foundingdate")
    private LocalDate foundingdate;

    @Column(name = "info", columnDefinition = "TEXT")
    private String info;

    @Column(name = "name", nullable = false, length = 255)
    private String name;

    @Column(name = "city", columnDefinition = "TEXT")
    private String city;

    @Column(name = "fullname", columnDefinition = "TEXT")
    private String fullname;

    @Column(name = "link", length = 255)
    private String link;

    // No-arg constructor for JPA
    public Club() {
    }

    // Constructor for setting id
    public Club(int id) {
        this.id = id;
    }

    // Getters and Setters
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getLongname() {
        return longname;
    }

    public void setLongname(String longname) {
        this.longname = longname;
    }

    public String getShortname() {
        return shortname;
    }

    public void setShortname(String shortname) {
        this.shortname = shortname;
    }

    public String getForeground() {
        return foreground;
    }

    public void setForeground(String foreground) {
        this.foreground = foreground;
    }

    public String getBackground() {
        return background;
    }

    public void setBackground(String background) {
        this.background = background;
    }

    public LocalDate getFoundingdate() {
        return foundingdate;
    }

    public void setFoundingdate(LocalDate foundingdate) {
        this.foundingdate = foundingdate;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getFullname() {
        return fullname;
    }

    public void setFullname(String fullname) {
        this.fullname = fullname;
    }

    public String getLink() {
        return link;
    }

    public void setLink(String link) {
        this.link = link;
    }
}

Ich habe danach zu Testzwecken die Länge von Foreground auf 8 gesetzt:
Java:
@Column(name = "foreground", length = 8)
    private String foreground;
Danach habe ich das Programm neugestartet (Main-Klasse):

Java:
package org.mjannek;

import org.hibernate.*;
import org.mjannek.database.*;

public class Main {
    public static void main(String[] args) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction transaction = null;
        try {
            transaction = session.beginTransaction();
            // Erstelle ein neues Team

            // Transaktion abschließen
            transaction.commit();
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
        } finally {
            session.close();
        }

        // Schließen der SessionFactory
        HibernateUtil.shutdown();
    }
}


Java:
package org.mjannek.database;

import javax.persistence.*;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.reflections.*;

public class HibernateUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();


    private static SessionFactory buildSessionFactory() {
        try {
            Configuration configuration = new Configuration();
            configuration.configure();

            // Automatische Erkennung aller Entitäten im Paket
            Reflections reflections = new Reflections("org.mjannek.sport.buli.tables");
            for (Class<?> clazz : reflections.getTypesAnnotatedWith(Entity.class)) {
                configuration.addAnnotatedClass(clazz);
            }

            return configuration.buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public static void shutdown() {
        getSessionFactory().close();
    }
}



Code:
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- JDBC Database connection settings -->
        <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://server:3306/schema</property>
        <property name="hibernate.connection.username">user</property>
        <property name="hibernate.connection.password">pw</property>

        <!-- JDBC connection pool settings -->
        <property name="hibernate.c3p0.min_size">5</property>
        <property name="hibernate.c3p0.max_size">20</property>
        <property name="hibernate.c3p0.timeout">300</property>
        <property name="hibernate.c3p0.max_statements">50</property>
        <property name="hibernate.c3p0.idle_test_period">3000</property>

        <!-- Specify dialect -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="hibernate.show_sql">true</property>

        <!-- Automatic detection of annotated entities -->
        <property name="hibernate.archive.autodetection">class,hbm</property>

        <!-- Schema generation strategy -->
        <property name="hibernate.hbm2ddl.auto">update</property>
    </session-factory>
</hibernate-configuration>

Ich erhalte keine Fehlermeldung, aber es werden auch keine Änderungen übernommen
 

MJannek

Bekanntes Mitglied
Außerdem möchte ich die folgende Klasse an Entity und Column anpassen
Java:
package org.mjannek.sql;

public class Query {
    private StringBuilder queryBuilder;
    private final String LINE_BREAK = "\n";
    private final String SPACE = " ";
    private final String COLON = ":";
    private final String VARIABEL = "?";
    private final String BRACKET_LEFT = "(";
    private final String BRACKET_RIGHT = ")";
    private final String COMMA = ",";
    private final String EQUALS = "=";
    private final String LESS = "<";
    private final String LESS_EQUALS = "<=";
    private final String GREATER = ">";
    private final String GREATER_EQUALS = ">=";
    private final String NOT_EQUALS = "!=";
    private final String PLUS = "+";
    private final String MINUS = "-";
    private final String TIMES = "*";
    private final String DIVIDE = "/";
    private final String ADD = "ADD";
    private final String ADD_CONSTRAINT = "ADD CONSTRAINT";
    private final String ALL = "ALL";
    private final String ALTER = "ALTER";
    private final String ALTER_COLUMN = "ALTER COLUMN";
    private final String ALTER_TABLE = "ALTER TABLE";
    private final String AND = "AND";
    private final String ANY = "ANY";
    private final String AS = "AS";
    private final String ASC = "ASC";
    private final String BACKUP_DATABASE = "BACKUP DATABASE";
    private final String BETWEEN = "BETWEEN";
    private final String CASE = "CASE";
    private final String CHECK = "CHECK";
    private final String COLUMN = "COLUMN";
    private final String CONCAT = "CONCAT";
    private final String CONSTRAINT = "CONSTRAINT";
    private final String COUNT = "COUNT";
    private final String COUNTALL = "COUNT(*)";
    private final String CREATE = "CREATE";
    private final String CREATE_DATABASE = "CREATE DATABASE";
    private final String CREATE_INDEX = "CREATE INDEX";
    private final String CREATE_OR_REPLACE_VIEW = "CREATE OR REPLACE VIEW";
    private final String CREATE_TABLE = "CREATE TABLE";
    private final String CREATE_PROCEDURE = "CREATE PROCEDURE";
    private final String CREATE_UNIQUE_INDEX = "CREATE UNIQUE INDEX";
    private final String CREATE_VIEW = "CREATE VIEW";
    private final String DATABASE = "DATABASE";
    private final String DEFAULT = "DEFAULT";
    private final String DELETE = "DELETE";
    private final String DELETE_FROM = "DELETE FROM";
    private final String DESC = "DESC";
    private final String DISTINCT = "DISTINCT";
    private final String DROP = "DROP";
    private final String DROP_COLUMN = "DROP COLUMN";
    private final String DROP_CONSTRAINT = "DROP CONSTRAINT";
    private final String DROP_DATABASE = "DROP DATABASE";
    private final String DROP_DEFAULT = "DROP DEFAULT";
    private final String DROP_INDEX = "DROP INDEX";
    private final String DROP_TABLE = "DROP TABLE";
    private final String DROP_VIEW = "DROP VIEW";
    private final String ELSE = "ELSE";
    private final String END = "END";
    private final String EXEC = "EXEC";
    private final String EXISTS = "EXISTS";
    private final String FOREIGN_KEY = "FOREIGN KEY";
    private final String FROM = "FROM";
    private final String FULL_OUTER_JOIN = "FULL OUTER JOIN";
    private final String GROUP_BY = "GROUP BY";
    private final String HAVING = "HAVING";
    private final String IF_NULL = "IFNULL";
    private final String IN = "IN";
    private final String INDEX = "INDEX";
    private final String INNER_JOIN = "INNER JOIN";
    private final String INSERT_IGNORE_INTO = "INSERT IGNORE INTO";
    private final String INSERT_INTO = "INSERT INTO";
    private final String INSERT_INTO_SELECT = "INSERT INTO SELECT";
    private final String IS_NULL = "IS NULL";
    private final String IS_NOT_NULL = "IS NOT NULL";
    private final String JOIN = "JOIN";
    private final String LEFT_JOIN = "LEFT JOIN";
    private final String LIKE = "LIKE";
    private final String LIMIT = "LIMIT";
    private final String MIN = "MIN";
    private final String MAX = "MAX";
    private final String NOT = "NOT";
    private final String NOT_BETWEEN = " NOT BETWEEN";
    private final String NOT_NULL = "NOT NULL";
    private final String NULL = "NULL";
    private final String OFFSET = "OFFSET";
    private final String ON = "ON";
    private final String OR = "OR";
    private final String ORDER_BY = "ORDER BY";
    private final String OUTER_JOIN = "OUTER JOIN";
    private final String PRIMARY_KEY = "PRIMARY KEY";
    private final String PROCEDURE = "PROCEDURE";
    private final String RIGHT_JOIN = "RIGHT JOIN";
    private final String ROWNUM = "ROWNUM";
    private final String SUM = "SUM";
    private final String SELECT = "SELECT";
    private final String SELECT_ALL = "SELECT * ";
    private final String SELECT_DISTINCT = "SELECT DISTINCT";
    private final String SELECT_INTO = "SELECT INTO";
    private final String SELECT_TOP = "SELECT TOP";
    private final String SET = "SET";
    private final String TABLE = "TABLE";
    private final String THEN = "THEN";
    private final String TOP = "TOP";
    private final String TRUNCATE_TABLE = "TRUNCATE TABLE";
    private final String UNION = "UNION";
    private final String UNION_ALL = "UNION ALL";
    private final String UNIQUE = "UNIQUE";
    private final String UPDATE = "UPDATE";
    private final String VALUES = "VALUES";
    private final String VIEW = "VIEW";
    private final String WHEN = "WHEN";
    private final String WHERE = "WHERE";


    public Query() {
        queryBuilder = new StringBuilder();
    }
    public Query(String query) {
        queryBuilder = new StringBuilder(query);
    }

    public Query and() {
        queryBuilder.append(AND).append(SPACE);
        return this;
    }

    public Query and(String condition) {
        queryBuilder.append(AND).append(SPACE).append(condition).append(SPACE);
        return this;
    }
    public Query and(Column condition) {
        queryBuilder.append(AND).append(SPACE).append(condition.getFullName()).append(SPACE);
        return this;
    }

    public Query as() {
        queryBuilder.append(AS).append(SPACE);
        return this;
    }

    public Query as(String as) {
        queryBuilder.append(AS).append(SPACE).append(as).append(SPACE);
        return this;
    }

    public Query as(String value, String as) {
        queryBuilder.append(value).append(SPACE).append(AS).append(SPACE).append(as).append(SPACE);
        return this;
    }

    public Query asc(){
        queryBuilder.append(ASC);
        return this;
    }

    public Query between(Column column, Object value1, Object value2) {
        queryBuilder.append(column.getFullName()).append(SPACE).append(BETWEEN).append(SPACE).append(value1).append(SPACE).append(AND).append(SPACE).append(value2).append(SPACE);
        return this;
    }

    public Query caseSQL() {
        queryBuilder.append(CASE).append(SPACE);
        return this;
    }

    public Query colon() {
        queryBuilder.append("'").append(COLON).append("'");
        return this;
    }

    public Query comma() {
        queryBuilder.append(COMMA).append(SPACE);
        return this;
    }

    public Query concat() {
        queryBuilder.append(CONCAT);
        return this;
    }

    public Query count(Column column) {
        queryBuilder.append(COUNT).append(BRACKET_LEFT).append(column.getFullName()).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }
    public Query count(String column) {
        queryBuilder.append(COUNT).append(BRACKET_LEFT).append(column).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query countAll() {
        queryBuilder.append(COUNTALL).append(SPACE);
        return this;
    }

    public Query desc(){
        queryBuilder.append(DESC);
        return this;
    }

    public Query deleteFrom(Table table) {
        queryBuilder.append(DELETE_FROM).append(SPACE).append(table.getTableName()).append(SPACE);
        return this;
    }

    public Query distinct() {
        queryBuilder.append(DISTINCT).append(SPACE);
        return this;
    }

    public Query divide() {
        queryBuilder.append(DIVIDE).append(SPACE);
        return this;
    }

    public Query divide(int num) {
        queryBuilder.append(DIVIDE).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query drop() {
        queryBuilder.append(DROP).append(SPACE);
        return this;
    }

    public Query elseSQL() {
        queryBuilder.append(ELSE).append(SPACE);
        return this;
    }
    public Query elseSQL(int num) {
        queryBuilder.append(ELSE).append(SPACE).append(num).append(SPACE);
        return this;
    }
    public Query elseSQL(String condition) {
        queryBuilder.append(ELSE).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query end() {
        queryBuilder.append(END).append(SPACE);
        return this;
    }

    public Query equal() {
        queryBuilder.append(EQUALS).append(SPACE);
        return this;
    }

    public Query equal(String condition) {
        queryBuilder.append(EQUALS).append(SPACE).append(condition).append(SPACE);
        return this;
    }
    public Query equal(Column condition) {
        queryBuilder.append(EQUALS).append(SPACE).append(condition.getFullName()).append(SPACE);
        return this;
    }

    public Query equal(int num) {
        queryBuilder.append(EQUALS).append(SPACE).append(num).append(SPACE);
        return this;
    }
    public Query from() {
        queryBuilder.append(FROM).append(SPACE);
        return this;
    }
    public Query from(String table) {
        queryBuilder.append(FROM).append(SPACE).append(table).append(SPACE);
        return this;
    }
    public Query from(Table table) {
        queryBuilder.append(FROM).append(SPACE).append(table.getTableName()).append(SPACE);
        return this;
    }

    public Query greater() {
        queryBuilder.append(GREATER).append(SPACE);
        return this;
    }

    public Query greater(int num) {
        queryBuilder.append(GREATER).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query greater(String condition) {
        queryBuilder.append(GREATER).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query greaterEquals() {
        queryBuilder.append(GREATER_EQUALS).append(SPACE);
        return this;
    }

    public Query greaterEquals(int num) {
        queryBuilder.append(GREATER_EQUALS).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query greaterEquals(String condition) {
        queryBuilder.append(GREATER_EQUALS).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query groupBy() {
        queryBuilder.append(GROUP_BY).append(SPACE);
        return this;
    }

    public Query groupBy(String columns) {
        queryBuilder.append(GROUP_BY).append(SPACE).append(columns).append(SPACE);
        return this;
    }
    public Query groupBy(Column column) {
        queryBuilder.append(GROUP_BY).append(SPACE).append(column.getFullName()).append(SPACE);
        return this;
    }

    public Query groupBy(Column[] columns) {
        if (columns == null || columns.length == 0) {
            throw new IllegalArgumentException("Columns array must not be null or empty.");
        }

        // Ensure queryBuilder is initialized
        if (queryBuilder == null) {
            queryBuilder = new StringBuilder();
        }

        // Start building the query
        queryBuilder.append(GROUP_BY)
                .append(SPACE);

        // Convert Column[] to String[]
        String[] columnNames = new String[columns.length];
        for (int i = 0; i < columns.length; i++) {
            columnNames[i] = columns[i].getFullName(); // Assuming Column has getColumnName() method
        }

        // Join column names with ", "
        queryBuilder.append(String.join(COMMA + SPACE, columnNames));
        queryBuilder.append(SPACE);

        return this;
    }

    public Query having(String condition) {
        queryBuilder.append(HAVING).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query ifNull(Column column, Object nullValue) {
        queryBuilder.append(IF_NULL).append(BRACKET_LEFT).append(column.getFullName()).append(COMMA).append(SPACE).append(nullValue).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }
    public Query ifNull(String column, Object nullValue) {
        queryBuilder.append(IF_NULL).append(BRACKET_LEFT).append(column).append(COMMA).append(SPACE).append(nullValue).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query in(Column[] columns) {
        if (columns == null || columns.length == 0) {
            throw new IllegalArgumentException("Columns array must not be null or empty.");
        }

        // Ensure queryBuilder is initialized
        if (queryBuilder == null) {
            queryBuilder = new StringBuilder();
        }

        // Start building the query
        queryBuilder.append(IN)
                .append(BRACKET_LEFT);

        // Convert Column[] to String[]
        String[] columnNames = new String[columns.length];
        for (int i = 0; i < columns.length; i++) {
            columnNames[i] = columns[i].getFullName(); // Assuming Column has getColumnName() method
        }

        // Join column names with ", "
        queryBuilder.append(String.join(COMMA + SPACE, columnNames));
        queryBuilder.append(BRACKET_RIGHT);

        return this;
    }

    public Query innerJoin(Table table) {
        queryBuilder.append(INNER_JOIN).append(SPACE).append(table.getTableName()).append(SPACE);
        return this;
    }
    public Query innerJoin(String table) {
        queryBuilder.append(INNER_JOIN).append(SPACE).append(table).append(SPACE);
        return this;
    }
    public Query insertIgnoreInto(Table table, Column[] columns) {
        if (columns == null || columns.length == 0) {
            throw new IllegalArgumentException("Columns array must not be null or empty.");
        }

        // Ensure queryBuilder is initialized
        if (queryBuilder == null) {
            queryBuilder = new StringBuilder();
        }

        // Start building the query
        queryBuilder.append(INSERT_IGNORE_INTO)
                .append(SPACE)
                .append(table.getTableName())
                .append(SPACE)
                .append(BRACKET_LEFT);

        // Convert Column[] to String[]
        String[] columnNames = new String[columns.length];
        for (int i = 0; i < columns.length; i++) {
            columnNames[i] = columns[i].getFullName(); // Assuming Column has getColumnName() method
        }

        // Join column names with ", "
        queryBuilder.append(String.join(COMMA + SPACE, columnNames));
        queryBuilder.append(SPACE)
                .append(BRACKET_RIGHT);

        return this;
    }

    public Query insertInto(Table table, Column columns) {
        queryBuilder.append(INSERT_INTO).append(SPACE).append(table.getTableName()).append(SPACE).append(BRACKET_LEFT).append(columns.getFullName()).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query insertInto(String table, String columns) {
        queryBuilder.append(INSERT_INTO).append(SPACE).append(table).append(SPACE).append(BRACKET_LEFT).append(columns).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query insertInto(Table table, Column[] columns) {
        if (columns == null || columns.length == 0) {
            throw new IllegalArgumentException("Columns array must not be null or empty.");
        }

        // Ensure queryBuilder is initialized
        if (queryBuilder == null) {
            queryBuilder = new StringBuilder();
        }

        // Start building the query
        queryBuilder.append(INSERT_INTO)
                .append(SPACE)
                .append(table.getTableName())
                .append(SPACE)
                .append(BRACKET_LEFT);

        // Convert Column[] to String[]
        String[] columnNames = new String[columns.length];
        for (int i = 0; i < columns.length; i++) {
            columnNames[i] = columns[i].getFullName(); // Assuming Column has getColumnName() method
        }

        // Join column names with ", "
        queryBuilder.append(String.join(COMMA + SPACE, columnNames));
        queryBuilder.append(SPACE)
                .append(BRACKET_RIGHT);

        return this;
    }


    public Query isNotNull(Column column) {
        queryBuilder.append(column.getFullName()).append(SPACE).append(IS_NOT_NULL).append(SPACE);
        return this;
    }

    public Query isNull(Column column) {
        queryBuilder.append(column.getFullName()).append(SPACE).append(IS_NULL).append(SPACE);
        return this;
    }

    public Query join(Table table) {
        queryBuilder.append(JOIN).append(SPACE).append(table.getTableName()).append(SPACE);
        return this;
    }
    public Query join(String table) {
        queryBuilder.append(JOIN).append(SPACE).append(table).append(SPACE);
        return this;
    }

    public Query leftBracket() {
        queryBuilder.append(SPACE).append(BRACKET_LEFT);
        return this;
    }

    public Query leftBracket(String value) {
        queryBuilder.append(BRACKET_LEFT).append(value).append(SPACE);
        return this;
    }

    public Query leftBracket(Column value) {
        queryBuilder.append(BRACKET_LEFT).append(value.getFullName()).append(SPACE);
        return this;
    }
    public Query leftBracket(Table value) {
        queryBuilder.append(BRACKET_LEFT).append(value.getTableName()).append(SPACE);
        return this;
    }

    public Query leftJoin(Table table) {
        queryBuilder.append(LEFT_JOIN).append(SPACE).append(table.getTableName()).append(SPACE);
        return this;
    }

    public Query leftJoin(String table) {
        queryBuilder.append(LEFT_JOIN).append(SPACE).append(table).append(SPACE);
        return this;
    }

    public Query less() {
        queryBuilder.append(LESS).append(SPACE);
        return this;
    }

    public Query less(int num) {
        queryBuilder.append(LESS).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query less(String condition) {
        queryBuilder.append(LESS).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query lessEquals() {
        queryBuilder.append(LESS_EQUALS).append(SPACE);
        return this;
    }

    public Query lessEquals(int num) {
        queryBuilder.append(LESS_EQUALS).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query lessEquals(String condition) {
        queryBuilder.append(LESS_EQUALS).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query like() {
        queryBuilder.append(LIKE).append(SPACE);
        return this;
    }

    public Query like(String condition) {
        queryBuilder.append(LIKE).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query limit(int limit) {
        queryBuilder.append(LIMIT).append(SPACE).append(limit).append(SPACE);
        return this;
    }

    public Query lineBreak() {
        queryBuilder.append(LINE_BREAK);
        return this;
    }

    public Query max(Column column) {
        queryBuilder.append(MAX).append(BRACKET_LEFT).append(column.getFullName()).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }
    public Query max(String column) {
        queryBuilder.append(MAX).append(BRACKET_LEFT).append(column).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query min(Column column) {
        queryBuilder.append(MIN).append(BRACKET_LEFT).append(column.getFullName()).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }
    public Query min(String column) {
        queryBuilder.append(MIN).append(BRACKET_LEFT).append(column).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query minus() {
        queryBuilder.append(MINUS).append(SPACE);
        return this;
    }

    public Query minus(int num) {
        queryBuilder.append(MINUS).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query notBetween(Column column, Object value1, Object value2) {
        queryBuilder.append(column.getFullName()).append(SPACE).append(NOT_BETWEEN).append(SPACE).append(value1).append(SPACE).append(AND).append(SPACE).append(value2).append(SPACE);
        return this;
    }

    public Query notEquals() {
        queryBuilder.append(NOT_EQUALS).append(SPACE).append(VARIABEL).append(SPACE);
        return this;
    }

    public Query notEquals(int num) {
        queryBuilder.append(NOT_EQUALS).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query notEquals(String condition) {
        queryBuilder.append(NOT_EQUALS).append(SPACE).append(condition).append(SPACE);
        return this;
    }
    public Query notEquals(Column condition) {
        queryBuilder.append(NOT_EQUALS).append(SPACE).append(condition.getFullName()).append(SPACE);
        return this;
    }

    public Query nullSQL() {
        queryBuilder.append(NULL).append(SPACE);
        return this;
    }

    public Query offset(int offset) {
        queryBuilder.append(OFFSET).append(SPACE).append(offset).append(SPACE);
        return this;
    }

    public Query on() {
        queryBuilder.append(ON).append(SPACE);
        return this;
    }

    public Query on(String value) {
        queryBuilder.append(ON).append(SPACE).append(value).append(SPACE);
        return this;
    }
    public Query on(Column value) {
        queryBuilder.append(ON).append(SPACE).append(value.getFullName()).append(SPACE);
        return this;
    }

    public Query or() {
        queryBuilder.append(OR).append(SPACE);
        return this;
    }

    public Query or(String condition) {
        queryBuilder.append(OR).append(SPACE).append(condition).append(SPACE);
        return this;
    }
    public Query or(Column condition) {
        queryBuilder.append(OR).append(SPACE).append(condition.getFullName()).append(SPACE);
        return this;
    }

    public Query orderBy() {
        queryBuilder.append(ORDER_BY).append(SPACE);
        return this;
    }

    public Query orderBy(String columns) {
        queryBuilder.append(ORDER_BY).append(SPACE).append(columns).append(SPACE);
        return this;
    }
    public Query orderBy(Column columns) {
        queryBuilder.append(ORDER_BY).append(SPACE).append(columns.getFullName()).append(SPACE);
        return this;
    }
    public Query orderBy(String[] columns) {
        if (columns == null || columns.length == 0) {
            throw new IllegalArgumentException("Columns array must not be null or empty.");
        }

        queryBuilder.append(ORDER_BY).append(SPACE);
        queryBuilder.append(String.join(COMMA + SPACE, columns));
        queryBuilder.append(SPACE);
        return this;
    }
    public Query orderBy(Column[] columns) {
        if (columns == null || columns.length == 0) {
            throw new IllegalArgumentException("Columns array must not be null or empty.");
        }

        // Ensure queryBuilder is initialized
        if (queryBuilder == null) {
            queryBuilder = new StringBuilder();
        }

        // Start building the query
        queryBuilder.append(ORDER_BY)
                .append(SPACE);

        // Convert Column[] to String[]
        String[] columnNames = new String[columns.length];
        for (int i = 0; i < columns.length; i++) {
            columnNames[i] = columns[i].getFullName(); // Assuming Column has getColumnName() method
        }

        // Join column names with ", "
        queryBuilder.append(String.join(COMMA + SPACE, columnNames));
        queryBuilder.append(SPACE);

        return this;
    }
    public Query plus() {
        queryBuilder.append(PLUS).append(SPACE);
        return this;
    }

    public Query plus(int num) {
        queryBuilder.append(PLUS).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query rightBracket() {
        queryBuilder.append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query rightBracket(String value) {
        queryBuilder.append(BRACKET_RIGHT).append(value).append(SPACE);
        return this;
    }

    public Query rightJoin(Table table) {
        queryBuilder.append(RIGHT_JOIN).append(SPACE).append(table.getTableName()).append(SPACE);
        return this;
    }
    public Query rightJoin(String table) {
        queryBuilder.append(RIGHT_JOIN).append(SPACE).append(table).append(SPACE);
        return this;
    }

    public Query select() {
        queryBuilder.append(SELECT).append(SPACE);
        return this;
    }
    public Query select(int num) {
        queryBuilder.append(SELECT).append(SPACE).append(num).append(SELECT);
        return this;
    }

    public Query select(Column columns) {
        queryBuilder.append(SELECT).append(SPACE).append(columns.getFullName()).append(SPACE);
        return this;
    }
    public Query select(String columns) {
        queryBuilder.append(SELECT).append(SPACE).append(columns).append(SPACE);
        return this;
    }

    public Query select(String[] columns) {
        if (columns == null || columns.length == 0) {
            throw new IllegalArgumentException("Columns array must not be null or empty.");
        }

        queryBuilder.append(SELECT).append(SPACE);
        queryBuilder.append(String.join(COMMA + SPACE, columns));
        queryBuilder.append(SPACE);
        return this;
    }

    public Query select(Column[] columns) {
        if (columns == null || columns.length == 0) {
            throw new IllegalArgumentException("Columns array must not be null or empty.");
        }

        // Ensure queryBuilder is initialized
        if (queryBuilder == null) {
            queryBuilder = new StringBuilder();
        }

        // Start building the query
        queryBuilder.append(SELECT)
                .append(SPACE);

        // Convert Column[] to String[]
        String[] columnNames = new String[columns.length];
        for (int i = 0; i < columns.length; i++) {
            columnNames[i] = columns[i].getFullName(); // Assuming Column has getColumnName() method
        }

        // Join column names with ", "
        queryBuilder.append(String.join(COMMA + SPACE, columnNames));
        queryBuilder.append(SPACE);

        return this;
    }

    public Query selectAll() {
        queryBuilder.append(SELECT_ALL).append(SPACE);
        return this;
    }

    public Query selectDistinct() {
        queryBuilder.append(SELECT).append(SPACE).append(DISTINCT).append(SPACE);
        return this;
    }
    public Query selectDistinct(Column column) {
        queryBuilder.append(SELECT).append(SPACE).append(DISTINCT).append(SPACE).append(column.getFullName()).append(SPACE);
        return this;
    }

    public Query set(String condition) {
        queryBuilder.append(SET).append(SPACE).append(condition).append(SPACE);
        return this;
    }
    public Query set(Column condition) {
        queryBuilder.append(SET).append(SPACE).append(condition.getFullName()).append(SPACE);
        return this;
    }

    public Query str(String s) {
        queryBuilder.append(s).append(SPACE);
        return this;
    }
    public Query str(Column s) {
        queryBuilder.append(s.getFullName()).append(SPACE);
        return this;
    }

    public Query str(int num) {
        queryBuilder.append(num).append(SPACE);
        return this;
    }

    public Query sum() {
        queryBuilder.append(SUM);
        return this;
    }

    public Query sum(Column column) {
        queryBuilder.append(SUM).append(BRACKET_LEFT).append(column.getFullName()).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }
    public Query sum(String column) {
        queryBuilder.append(SUM).append(BRACKET_LEFT).append(column).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query then() {
        queryBuilder.append(THEN).append(SPACE);
        return this;
    }

    public Query then(String condition) {
        queryBuilder.append(THEN).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query then(int num) {
        queryBuilder.append(THEN).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query times() {
        queryBuilder.append(TIMES).append(SPACE);
        return this;
    }

    public Query times(int num) {
        queryBuilder.append(TIMES).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query union() {
        queryBuilder.append(UNION).append(SPACE);
        return this;
    }

    public Query unionAll() {
        queryBuilder.append(UNION).append(SPACE).append(ALL).append(SPACE);
        return this;
    }

    public Query update(Table table) {
        queryBuilder.append(UPDATE).append(SPACE).append(table.getTableName()).append(SPACE);
        return this;
    }
    public Query update(String table) {
        queryBuilder.append(UPDATE).append(SPACE).append(table).append(SPACE);
        return this;
    }

    public Query values() {
        queryBuilder.append(VALUES).append(SPACE).append(BRACKET_LEFT);
        return this;
    }

    public Query values(int count) {
        if (count <= 0) {
            throw new IllegalArgumentException("Count must be greater than zero.");
        }

        queryBuilder.append(VALUES).append(SPACE).append(BRACKET_LEFT);

        for (int i = 0; i < count; i++) {
            queryBuilder.append(VARIABEL);

            if (i < count - 1) {
                queryBuilder.append(COMMA).append(SPACE);
            }
        }

        queryBuilder.append(BRACKET_RIGHT).append(SPACE);

        return this;
    }

    public Query values(Column columns) {
        queryBuilder.append(VALUES).append(SPACE).append(BRACKET_LEFT).append(columns.getFullName()).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query values(String[] values) {
        if (values.length == 0) {
            throw new IllegalArgumentException("Attributes and values arrays must have the same length and cannot be empty.");
        }

        queryBuilder.append(VALUES).append(BRACKET_LEFT);
        queryBuilder.append("\"").append(values[0]).append("\"");
        for (int i = 1; i < values.length; i++) {
            queryBuilder.append(COMMA).append("\"").append(values[i]).append("\"");
        }


        queryBuilder.append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query variabel() {
        queryBuilder.append(VARIABEL).append(SPACE);
        return this;
    }

    public Query when() {
        queryBuilder.append(WHEN).append(SPACE);
        return this;
    }

    public Query when(String condition) {
        queryBuilder.append(WHEN).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query where() {
        queryBuilder.append(WHERE).append(SPACE);
        return this;
    }
    public Query where(String condition) {
        queryBuilder.append(WHERE).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query where(int condition) {
        queryBuilder.append(WHERE).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query where(Column condition) {
        queryBuilder.append(WHERE).append(SPACE).append(condition.getFullName()).append(SPACE);
        return this;
    }

    public Query where(String[] attributes, String[] values) {
        if (attributes.length != values.length || attributes.length == 0) {
            throw new IllegalArgumentException("Attributes and values arrays must have the same length and cannot be empty.");
        }

        queryBuilder.append(WHERE).append(SPACE);

        if (attributes.length == 1) {
            queryBuilder.append(attributes[0]).append(EQUALS).append("\"").append(values[0]).append("\"");
        } else {
            queryBuilder.append(attributes[0]).append("\"").append(EQUALS).append(values[0]).append("\"");
            for (int i = 1; i < attributes.length; i++) {
                queryBuilder.append(AND).append(attributes[i]).append(EQUALS).append("\"").append(values[i]).append("\"");
            }
        }

        queryBuilder.append(SPACE);
        return this;
    }

    public String build() {
        String query = queryBuilder.toString();
        if(!query.contains(";")){
            query = queryBuilder.append(";").toString();
        }
        return query.replace(" (", "(").replace(" )", ")").replace(" ,", ", ").replace("  "," ");
    }


}
 

Oneixee5

Top Contributor
Queries aus Strings zusammenbauen, das sollte man nicht tun - in keiner Programmiersprache. Du kannst dazu mal nach: SQL Injection googeln.

Du hattest auch geschrieben, dass du eine bestehende MySql reverse ingenieren möchtest. Jetzt erwartest du Änderungen an der DB. Da passt etwas nicht zusammen.
 

MJannek

Bekanntes Mitglied
Queries aus Strings zusammenbauen, das sollte man nicht tun - in keiner Programmiersprache. Du kannst dazu mal nach: SQL Injection googeln.

Du hattest auch geschrieben, dass du eine bestehende MySql reverse ingenieren möchtest. Jetzt erwartest du Änderungen an der DB. Da passt etwas nicht zusammen.
Vielen Dank für diesen Tipp
 

MJannek

Bekanntes Mitglied
Ich habe es jetzt himbekommen, Tabellen zu erstellen, jedoch werden Änderung nicht übernommen, wenn ich die Klassendefinitionen anpasse
Ich habe Club wie folgt, initial definiert:
Java:
package org.mjannek.sport.buli.tables;

import javax.persistence.*;
import java.time.LocalDate;

@Entity
@Table(name = "clubs", uniqueConstraints = {
        @UniqueConstraint(columnNames = "link"),
        @UniqueConstraint(columnNames = "longname")
})
public class Club {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(name = "longname", nullable = false, length = 255)
    private String longname;

    @Column(name = "shortname", nullable = false, length = 3)
    private String shortname;

    @Column(name = "foreground", length = 7)
    private String foreground;

    @Column(name = "background", length = 7)
    private String background;

    @Column(name = "foundingdate")
    private LocalDate foundingdate;

    @Column(name = "info", columnDefinition = "TEXT")
    private String info;

    @Column(name = "name", nullable = false, length = 255)
    private String name;

    @Column(name = "city", columnDefinition = "TEXT")
    private String city;

    @Column(name = "fullname", columnDefinition = "TEXT")
    private String fullname;

    @Column(name = "link", length = 255)
    private String link;

    // No-arg constructor for JPA
    public Club() {
    }

    // Constructor for setting id
    public Club(int id) {
        this.id = id;
    }

    // Getters and Setters
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getLongname() {
        return longname;
    }

    public void setLongname(String longname) {
        this.longname = longname;
    }

    public String getShortname() {
        return shortname;
    }

    public void setShortname(String shortname) {
        this.shortname = shortname;
    }

    public String getForeground() {
        return foreground;
    }

    public void setForeground(String foreground) {
        this.foreground = foreground;
    }

    public String getBackground() {
        return background;
    }

    public void setBackground(String background) {
        this.background = background;
    }

    public LocalDate getFoundingdate() {
        return foundingdate;
    }

    public void setFoundingdate(LocalDate foundingdate) {
        this.foundingdate = foundingdate;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getFullname() {
        return fullname;
    }

    public void setFullname(String fullname) {
        this.fullname = fullname;
    }

    public String getLink() {
        return link;
    }

    public void setLink(String link) {
        this.link = link;
    }
}

Ich habe danach zu Testzwecken die Länge von Foreground auf 8 gesetzt:
Java:
@Column(name = "foreground", length = 8)
    private String foreground;
Danach habe ich das Programm neugestartet (Main-Klasse):

Java:
package org.mjannek;

import org.hibernate.*;
import org.mjannek.database.*;

public class Main {
    public static void main(String[] args) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction transaction = null;
        try {
            transaction = session.beginTransaction();
            // Erstelle ein neues Team

            // Transaktion abschließen
            transaction.commit();
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
        } finally {
            session.close();
        }

        // Schließen der SessionFactory
        HibernateUtil.shutdown();
    }
}


Java:
package org.mjannek.database;

import javax.persistence.*;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.reflections.*;

public class HibernateUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();


    private static SessionFactory buildSessionFactory() {
        try {
            Configuration configuration = new Configuration();
            configuration.configure();

            // Automatische Erkennung aller Entitäten im Paket
            Reflections reflections = new Reflections("org.mjannek.sport.buli.tables");
            for (Class<?> clazz : reflections.getTypesAnnotatedWith(Entity.class)) {
                configuration.addAnnotatedClass(clazz);
            }

            return configuration.buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public static void shutdown() {
        getSessionFactory().close();
    }
}



Code:
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- JDBC Database connection settings -->
        <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://server:3306/schema</property>
        <property name="hibernate.connection.username">user</property>
        <property name="hibernate.connection.password">pw</property>

        <!-- JDBC connection pool settings -->
        <property name="hibernate.c3p0.min_size">5</property>
        <property name="hibernate.c3p0.max_size">20</property>
        <property name="hibernate.c3p0.timeout">300</property>
        <property name="hibernate.c3p0.max_statements">50</property>
        <property name="hibernate.c3p0.idle_test_period">3000</property>

        <!-- Specify dialect -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="hibernate.show_sql">true</property>

        <!-- Automatic detection of annotated entities -->
        <property name="hibernate.archive.autodetection">class,hbm</property>

        <!-- Schema generation strategy -->
        <property name="hibernate.hbm2ddl.auto">update</property>
    </session-factory>
</hibernate-configuration>

Ich erhalte keine Fehlermeldung, aber es werden auch keine Änderungen übernommen
Was ist der Fehler hier
 

MJannek

Bekanntes Mitglied
Queries aus Strings zusammenbauen, das sollte man nicht tun - in keiner Programmiersprache. Du kannst dazu mal nach: SQL Injection googeln.

Du hattest auch geschrieben, dass du eine bestehende MySql reverse ingenieren möchtest. Jetzt erwartest du Änderungen an der DB. Da passt etwas nicht zusammen.
Die Klassen haben ich bereits erfolgreich erstellt. Mir ging es jetzt nur aus Testzwecken darum, ob Änderungen der Klassendefinitionen automatisch übertragen werden
 

MJannek

Bekanntes Mitglied
Queries aus Strings zusammenbauen, das sollte man nicht tun - in keiner Programmiersprache. Du kannst dazu mal nach: SQL Injection googeln.

Du hattest auch geschrieben, dass du eine bestehende MySql reverse ingenieren möchtest. Jetzt erwartest du Änderungen an der DB. Da passt etwas nicht zusammen.
Ich habe mir SQL Injection angesehen, bin damit aber nicht zufrieden, Da ich mir ein String query fest vordefiniere:
Java:
String query = "Select * from users where userid > 1";
Ich möchte eher:
Java:
String query =
User.objects.filter(status_id__gt=1)[

/*User.objects.filter(status_id__gt=1)
ist ein Befehl aus den Django models in Python.
Das würde ich gerne ähnlich in Java umsetzen. NICHT mit: String query = "Select * from users where userid > 1"
*/
 

Marinek

Bekanntes Mitglied
Die Klassen haben ich bereits erfolgreich erstellt. Mir ging es jetzt nur aus Testzwecken darum, ob Änderungen der Klassendefinitionen automatisch übertragen werden
So wie ich das auf die schnelle überblickt habe, hast du die Länge eines Attributs geändert. Das wird Hibernate nicht in der Datenbank ändern.

Du musst ein Attribut hinzufügen.

Gruß,
Martin
 

MJannek

Bekanntes Mitglied
Ich habe mir folgendes erstellt:
Java:
package org.mjannek.database.entity;

import javax.persistence.*;
import org.mjannek.database.columns.number.*;


@MappedSuperclass

public abstract class BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Embedded
    private IdColumn id;

    public BaseEntity() {
        this.id = new IdColumn();
    }

    public BaseEntity(Integer id) {
        this.id = new IdColumn(id);
    }

    public BaseEntity(Integer id, Integer defaultValue) {
        this.id = new IdColumn(id);
        this.id.setDefaultValue(defaultValue);
    }

    public IdColumn getId() {
        return id;
    }

    public void setId(IdColumn id) {
        this.id = id;
    }

    public String getTableName() {
        Table tableAnnotation = getClass().getAnnotation(Table.class);
        String tableName;

        if (tableAnnotation != null) {
            tableName = tableAnnotation.name(); // Name aus der Annotation
        } else {
            // Fallback, falls @Table nicht vorhanden ist
            tableName = getClass().getSimpleName();
        }
        return tableName;
    }
}

Java:
package org.mjannek.database.columns;

import java.util.*;
import javax.persistence.Embeddable;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * Eine generische Klasse, die als Basismodell für verschiedene Spalten verwendet werden kann.
 * Die Klasse ist mit @Embeddable annotiert, sodass sie in JPA-Entitäten eingebettet werden kann.
 */
@Embeddable
public abstract class AbstractColumn<T extends Comparable<T>> implements Serializable, Comparable<AbstractColumn<T>> {
    private T value;
    private T defaultValue;
    private Class<T> type;
    private boolean nullable = true;
    private int length = 255;
    private Locale locale = Locale.getDefault();
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;

    // Standardkonstruktor für JPA
    public AbstractColumn() {
    }

    // Konstruktor mit Initialwert
    public AbstractColumn(T value) {
        this.value = value;
    }

    // Konstruktor mit Typ
    public AbstractColumn(Class<T> type) {
        this.type = type;
    }

    // Neuer Konstruktor mit Initialwert und Defaultwert
    public AbstractColumn(T value, T defaultValue) {
        this.value = value;
        this.defaultValue = defaultValue;
    }

    // Getter und Setter für den Wert
    public T getValue() {
        return value != null ? value : defaultValue;
    }

    public void setValue(T value) {
        validate(value);
        this.value = value;
    }

    public T getDefaultValue() {
        return defaultValue;
    }

    public void setDefaultValue(T defaultValue) {
        this.defaultValue = defaultValue;
    }

    public Class<T> getType() {
        return type;
    }

    public void setType(Class<T> type) {
        this.type = type;
    }

    public boolean isNullable() {
        return nullable;
    }

    public void setNullable(boolean nullable) {
        this.nullable = nullable;
    }

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public Locale getLocale() {
        return locale;
    }

    public void setLocale(Locale locale) {
        this.locale = locale;
    }

    public LocalDateTime getCreatedAt() {
        return createdAt;
    }

    public LocalDateTime getUpdatedAt() {
        return updatedAt;
    }

    // Audit-Methoden
    @PrePersist
    protected void onCreate() {
        createdAt = LocalDateTime.now();
        updatedAt = LocalDateTime.now();
    }

    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }

    // Validierungsmethode (Standard)
    protected void validate(T value) {
        // Standardmäßig keine Validierung
    }

    // Equals und HashCode
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        AbstractColumn<?> that = (AbstractColumn<?>) o;
        return Objects.equals(value, that.value);
    }

    @Override
    public int hashCode() {
        return value != null ? value.hashCode() : 0;
    }

    // Vergleichsmethode für sortierbare Spalten
    @Override
    public int compareTo(AbstractColumn<T> other) {
        return this.value.compareTo(other.getValue());
    }

    // JSON-Darstellung
    public String asJson() {
        return "{\"value\": \"" + value + "\"}";
    }

    @Override
    public String toString() {
        return String.valueOf(value);
    }
}

Java:
package org.mjannek.database.columns.datetime;

import java.io.*;
import java.time.*;
import java.util.*;
import javax.persistence.*;
import org.mjannek.database.columns.*;

@Embeddable
public class LocalDateColumn extends AbstractColumn<Date> implements Serializable {

    // Standardkonstruktor für JPA
    public LocalDateColumn() {
        super();
    }

    // Konstruktor mit Initialwert
    public LocalDateColumn(LocalDate value) {
        super(Date.from(value.atStartOfDay(ZoneId.systemDefault()).toInstant()));
    }

    // Konstruktor mit Initialwert und Defaultwert
    public LocalDateColumn(LocalDate value, LocalDate defaultValue) {
        super(Date.from(value.atStartOfDay(ZoneId.systemDefault()).toInstant()),
                Date.from(defaultValue.atStartOfDay(ZoneId.systemDefault()).toInstant()));
    }

    @Override
    public void setValue(Date value) {
        super.setValue(value);
    }

    public void setValue(LocalDate value) {
        super.setValue(Date.from(value.atStartOfDay(ZoneId.systemDefault()).toInstant()));
    }

    @Override
    public Date getValue() {
        return super.getValue();
    }

    public LocalDate getLocalDateValue() {
        return getValue().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    // Überschreibe equals und hashCode für korrekte Vergleichsoperationen
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        LocalDateColumn that = (LocalDateColumn) o;
        return Objects.equals(getValue(), that.getValue());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getValue());
    }

    // Überschreibe compareTo für sortierbare Spalten
    @Override
    public int compareTo(AbstractColumn<Date> other) {
        return this.getValue().compareTo(other.getValue());
    }

    // JSON-Darstellung
    @Override
    public String asJson() {
        return "{\"value\": \"" + getValue() + "\"}";
    }

    @Override
    public String toString() {
        return String.valueOf(getValue());
    }
}
Java:
package org.mjannek.database.columns.number;

import javax.persistence.*;
import java.io.Serializable;
import org.mjannek.database.columns.AbstractColumn;

@Embeddable
public class IdColumn extends AbstractColumn<Integer> implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private Integer id;

    // Standardkonstruktor für JPA
    public IdColumn() {
        super();
    }

    // Konstruktor mit Initialwert
    public IdColumn(Integer value) {
        super(value);
        this.id = value;
    }

    // Neuer Konstruktor mit Initialwert und Defaultwert
    public IdColumn(Integer value, Integer defaultValue) {
        super(value, defaultValue);
        this.id = value;
        this.setDefaultValue(defaultValue);
    }

    @Override
    public Integer getValue() {
        return id;
    }

    @Override
    public void setValue(Integer value) {
        this.id = value;
    }

    @PrePersist
    @Override
    protected void onCreate() {
        super.onCreate();
    }

    @PreUpdate
    @Override
    protected void onUpdate() {
        super.onUpdate();
    }

    @Override
    protected void validate(Integer value) {
        if (value < 0) {
            throw new IllegalArgumentException("ID cannot be negative");
        }
    }
}

Java:
package org.mjannek.database.columns.number;

import javax.persistence.*;
import org.mjannek.database.columns.AbstractColumn;

@Embeddable
public class IntegerColumn extends AbstractColumn<Integer> {

    // Standardkonstruktor für JPA
    public IntegerColumn() {
        super();
    }

    // Konstruktor mit Initialwert
    public IntegerColumn(Integer value) {
        super(value);
    }

    // Konstruktor mit Initialwert und Defaultwert
    public IntegerColumn(Integer value, Integer defaultValue) {
        super(value, defaultValue);
    }
}
Java:
package org.mjannek.database.columns.text;

import javax.persistence.*;
import org.mjannek.database.columns.AbstractColumn;

@Embeddable
public class StringColumn extends AbstractColumn<String> {

    // Standardkonstruktor für JPA
    public StringColumn() {
        super();
    }

    // Konstruktor mit Initialwert
    public StringColumn(String value) {
        super(value);
    }

    // Konstruktor mit Initialwert und Defaultwert
    public StringColumn(String value, String defaultValue) {
        super(value, defaultValue);
    }
}
Java:
package org.mjannek.database.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.persistence.*;

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Embedded
@Column
public @interface EmbeddedColumn {
    // Column attributes
    String name() default "";

    boolean unique() default false;

    boolean nullable() default true;

    boolean insertable() default true;

    boolean updatable() default true;

    String columnDefinition() default "";

    String table() default "";

    int length() default 255;

    int precision() default 0;

    int scale() default 0;
}
Java:
package org.mjannek.sport.buli.tables;

import javax.persistence.*;
import org.mjannek.database.annotation.EmbeddedColumn;
import org.mjannek.database.listener.EmbeddedColumnListener;
import org.mjannek.database.columns.text.StringColumn;
import org.mjannek.database.columns.number.IntegerColumn;
import org.mjannek.database.entity.BaseEntity;

@Entity
@Table(name = "test_entity")
public class TestEntity extends BaseEntity {
    
    @EmbeddedColumn(name = "test_string", nullable = false, length = 255)
    private StringColumn testString = new StringColumn();
    
    @EmbeddedColumn(name = "test_integer", nullable = false)
    private IntegerColumn testInteger = new IntegerColumn();

    // No-arg constructor for JPA
    public TestEntity() {
        super();
    }

    // Constructor for setting fields
    public TestEntity(String testString, Integer testInteger) {
        this.testString.setValue(testString);
        this.testInteger.setValue(testInteger);
    }

    // Getters and Setters
    public String getTestString() {
        return testString.getValue();
    }

    public void setTestString(String testString) {
        this.testString.setValue(testString);
    }

    public Integer getTestInteger() {
        return testInteger.getValue();
    }

    public void setTestInteger(Integer testInteger) {
        this.testInteger.setValue(testInteger);
    }
}

In EmbeddedColumn sind @Embedded und @Column rot unterstrichen mit folgender Fehlermeldung:

'@Embedded' not applicable to annotation type
'@Column' not applicable to annotation type

Ich möchte jedoch eine Annotation erstellen, die @Embedded und @Column kombiniert (falls möglich).
Vielen Dank im Voraus
 

Marinek

Bekanntes Mitglied
Dein Ansatz scheint falsch zu sein.

Selbst wenn das, was du da willst gehen würde, was nicht geht, weil man keine Annotationen in Java vererben kann, könnte Hibernate damit nicht umgehen.

Demzufolge wirst du dein Ziel, wie du es geschrieben hast, nicht erreichen.

WArum funktioniert das nicht, was @Oneixee5 in #28 geschrieben hat?

Warum braucht man eine Integer Column und String Column, wenn man einfach String und Integer nutzen kann?

Der Defaultwert kann ja einfach gesetzt werden:

Java:
private String testString = "Dies ist mein Default-Wert."

Kannst du nochmal vielleicht beschreiben, was du hast, was du machen willst? Am besten fachlich und nicht technisch.

Ich frage, wegen dem hier: https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem/66378#66378
 
Zuletzt bearbeitet:

mihe7

Top Contributor
Ich habe mir folgendes erstellt:
Wozu?!?

Ich möchte jedoch eine Annotation erstellen, die @Embedded und @Column kombiniert (falls möglich).
Das gibt konzeptionell schon keinen Sinn. Eingebettet werden Objekte, nicht Spalten. Und Objekte haben Attribute, keine Spalten. Die Attribute werden auf Spalten der DB abgebildet.

Allerdings weiß ich nicht, was das eigentlich werden soll, wenn es fertig ist. Jede DB kennt ihre Spalten, was willst Du das nochmal speichern?
 

MJannek

Bekanntes Mitglied
Weil ich meine Query Klasse verwenden möchte, statt Table dann BaseEntity und statt Column AbstactColumn
Java:
package org.mjannek.sql;

public class Query {
    private StringBuilder queryBuilder;
    private final String LINE_BREAK = "\n";
    private final String SPACE = " ";
    private final String COLON = ":";
    private final String VARIABEL = "?";
    private final String BRACKET_LEFT = "(";
    private final String BRACKET_RIGHT = ")";
    private final String COMMA = ",";
    private final String EQUALS = "=";
    private final String LESS = "<";
    private final String LESS_EQUALS = "<=";
    private final String GREATER = ">";
    private final String GREATER_EQUALS = ">=";
    private final String NOT_EQUALS = "!=";
    private final String PLUS = "+";
    private final String MINUS = "-";
    private final String TIMES = "*";
    private final String DIVIDE = "/";
    private final String ADD = "ADD";
    private final String ADD_CONSTRAINT = "ADD CONSTRAINT";
    private final String ALL = "ALL";
    private final String ALTER = "ALTER";
    private final String ALTER_COLUMN = "ALTER COLUMN";
    private final String ALTER_TABLE = "ALTER TABLE";
    private final String AND = "AND";
    private final String ANY = "ANY";
    private final String AS = "AS";
    private final String ASC = "ASC";
    private final String BACKUP_DATABASE = "BACKUP DATABASE";
    private final String BETWEEN = "BETWEEN";
    private final String CASE = "CASE";
    private final String CHECK = "CHECK";
    private final String COLUMN = "COLUMN";
    private final String CONCAT = "CONCAT";
    private final String CONSTRAINT = "CONSTRAINT";
    private final String COUNT = "COUNT";
    private final String COUNTALL = "COUNT(*)";
    private final String CREATE = "CREATE";
    private final String CREATE_DATABASE = "CREATE DATABASE";
    private final String CREATE_INDEX = "CREATE INDEX";
    private final String CREATE_OR_REPLACE_VIEW = "CREATE OR REPLACE VIEW";
    private final String CREATE_TABLE = "CREATE TABLE";
    private final String CREATE_PROCEDURE = "CREATE PROCEDURE";
    private final String CREATE_UNIQUE_INDEX = "CREATE UNIQUE INDEX";
    private final String CREATE_VIEW = "CREATE VIEW";
    private final String DATABASE = "DATABASE";
    private final String DEFAULT = "DEFAULT";
    private final String DELETE = "DELETE";
    private final String DELETE_FROM = "DELETE FROM";
    private final String DESC = "DESC";
    private final String DISTINCT = "DISTINCT";
    private final String DROP = "DROP";
    private final String DROP_COLUMN = "DROP COLUMN";
    private final String DROP_CONSTRAINT = "DROP CONSTRAINT";
    private final String DROP_DATABASE = "DROP DATABASE";
    private final String DROP_DEFAULT = "DROP DEFAULT";
    private final String DROP_INDEX = "DROP INDEX";
    private final String DROP_TABLE = "DROP TABLE";
    private final String DROP_VIEW = "DROP VIEW";
    private final String ELSE = "ELSE";
    private final String END = "END";
    private final String EXEC = "EXEC";
    private final String EXISTS = "EXISTS";
    private final String FOREIGN_KEY = "FOREIGN KEY";
    private final String FROM = "FROM";
    private final String FULL_OUTER_JOIN = "FULL OUTER JOIN";
    private final String GROUP_BY = "GROUP BY";
    private final String HAVING = "HAVING";
    private final String IF_NULL = "IFNULL";
    private final String IN = "IN";
    private final String INDEX = "INDEX";
    private final String INNER_JOIN = "INNER JOIN";
    private final String INSERT_IGNORE_INTO = "INSERT IGNORE INTO";
    private final String INSERT_INTO = "INSERT INTO";
    private final String INSERT_INTO_SELECT = "INSERT INTO SELECT";
    private final String IS_NULL = "IS NULL";
    private final String IS_NOT_NULL = "IS NOT NULL";
    private final String JOIN = "JOIN";
    private final String LEFT_JOIN = "LEFT JOIN";
    private final String LIKE = "LIKE";
    private final String LIMIT = "LIMIT";
    private final String MIN = "MIN";
    private final String MAX = "MAX";
    private final String NOT = "NOT";
    private final String NOT_BETWEEN = " NOT BETWEEN";
    private final String NOT_NULL = "NOT NULL";
    private final String NULL = "NULL";
    private final String OFFSET = "OFFSET";
    private final String ON = "ON";
    private final String OR = "OR";
    private final String ORDER_BY = "ORDER BY";
    private final String OUTER_JOIN = "OUTER JOIN";
    private final String PRIMARY_KEY = "PRIMARY KEY";
    private final String PROCEDURE = "PROCEDURE";
    private final String RIGHT_JOIN = "RIGHT JOIN";
    private final String ROWNUM = "ROWNUM";
    private final String SUM = "SUM";
    private final String SELECT = "SELECT";
    private final String SELECT_ALL = "SELECT * ";
    private final String SELECT_DISTINCT = "SELECT DISTINCT";
    private final String SELECT_INTO = "SELECT INTO";
    private final String SELECT_TOP = "SELECT TOP";
    private final String SET = "SET";
    private final String TABLE = "TABLE";
    private final String THEN = "THEN";
    private final String TOP = "TOP";
    private final String TRUNCATE_TABLE = "TRUNCATE TABLE";
    private final String UNION = "UNION";
    private final String UNION_ALL = "UNION ALL";
    private final String UNIQUE = "UNIQUE";
    private final String UPDATE = "UPDATE";
    private final String VALUES = "VALUES";
    private final String VIEW = "VIEW";
    private final String WHEN = "WHEN";
    private final String WHERE = "WHERE";


    public Query() {
        queryBuilder = new StringBuilder();
    }
    public Query(String query) {
        queryBuilder = new StringBuilder(query);
    }

    public Query and() {
        queryBuilder.append(AND).append(SPACE);
        return this;
    }

    public Query and(String condition) {
        queryBuilder.append(AND).append(SPACE).append(condition).append(SPACE);
        return this;
    }
    public Query and(Column condition) {
        queryBuilder.append(AND).append(SPACE).append(condition.getFullName()).append(SPACE);
        return this;
    }

    public Query as() {
        queryBuilder.append(AS).append(SPACE);
        return this;
    }

    public Query as(String as) {
        queryBuilder.append(AS).append(SPACE).append(as).append(SPACE);
        return this;
    }

    public Query as(String value, String as) {
        queryBuilder.append(value).append(SPACE).append(AS).append(SPACE).append(as).append(SPACE);
        return this;
    }

    public Query asc(){
        queryBuilder.append(ASC);
        return this;
    }

    public Query between(Column column, Object value1, Object value2) {
        queryBuilder.append(column.getFullName()).append(SPACE).append(BETWEEN).append(SPACE).append(value1).append(SPACE).append(AND).append(SPACE).append(value2).append(SPACE);
        return this;
    }

    public Query caseSQL() {
        queryBuilder.append(CASE).append(SPACE);
        return this;
    }

    public Query colon() {
        queryBuilder.append("'").append(COLON).append("'");
        return this;
    }

    public Query comma() {
        queryBuilder.append(COMMA).append(SPACE);
        return this;
    }

    public Query concat() {
        queryBuilder.append(CONCAT);
        return this;
    }

    public Query count(Column column) {
        queryBuilder.append(COUNT).append(BRACKET_LEFT).append(column.getFullName()).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }
    public Query count(String column) {
        queryBuilder.append(COUNT).append(BRACKET_LEFT).append(column).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query countAll() {
        queryBuilder.append(COUNTALL).append(SPACE);
        return this;
    }

    public Query desc(){
        queryBuilder.append(DESC);
        return this;
    }

    public Query deleteFrom(Table table) {
        queryBuilder.append(DELETE_FROM).append(SPACE).append(table.getTableName()).append(SPACE);
        return this;
    }

    public Query distinct() {
        queryBuilder.append(DISTINCT).append(SPACE);
        return this;
    }

    public Query divide() {
        queryBuilder.append(DIVIDE).append(SPACE);
        return this;
    }

    public Query divide(int num) {
        queryBuilder.append(DIVIDE).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query drop() {
        queryBuilder.append(DROP).append(SPACE);
        return this;
    }

    public Query elseSQL() {
        queryBuilder.append(ELSE).append(SPACE);
        return this;
    }
    public Query elseSQL(int num) {
        queryBuilder.append(ELSE).append(SPACE).append(num).append(SPACE);
        return this;
    }
    public Query elseSQL(String condition) {
        queryBuilder.append(ELSE).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query end() {
        queryBuilder.append(END).append(SPACE);
        return this;
    }

    public Query equal() {
        queryBuilder.append(EQUALS).append(SPACE);
        return this;
    }

    public Query equal(String condition) {
        queryBuilder.append(EQUALS).append(SPACE).append(condition).append(SPACE);
        return this;
    }
    public Query equal(Column condition) {
        queryBuilder.append(EQUALS).append(SPACE).append(condition.getFullName()).append(SPACE);
        return this;
    }

    public Query equal(int num) {
        queryBuilder.append(EQUALS).append(SPACE).append(num).append(SPACE);
        return this;
    }
    public Query from() {
        queryBuilder.append(FROM).append(SPACE);
        return this;
    }
    public Query from(String table) {
        queryBuilder.append(FROM).append(SPACE).append(table).append(SPACE);
        return this;
    }
    public Query from(Table table) {
        queryBuilder.append(FROM).append(SPACE).append(table.getTableName()).append(SPACE);
        return this;
    }

    public Query greater() {
        queryBuilder.append(GREATER).append(SPACE);
        return this;
    }

    public Query greater(int num) {
        queryBuilder.append(GREATER).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query greater(String condition) {
        queryBuilder.append(GREATER).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query greaterEquals() {
        queryBuilder.append(GREATER_EQUALS).append(SPACE);
        return this;
    }

    public Query greaterEquals(int num) {
        queryBuilder.append(GREATER_EQUALS).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query greaterEquals(String condition) {
        queryBuilder.append(GREATER_EQUALS).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query groupBy() {
        queryBuilder.append(GROUP_BY).append(SPACE);
        return this;
    }

    public Query groupBy(String columns) {
        queryBuilder.append(GROUP_BY).append(SPACE).append(columns).append(SPACE);
        return this;
    }
    public Query groupBy(Column column) {
        queryBuilder.append(GROUP_BY).append(SPACE).append(column.getFullName()).append(SPACE);
        return this;
    }

    public Query groupBy(Column[] columns) {
        if (columns == null || columns.length == 0) {
            throw new IllegalArgumentException("Columns array must not be null or empty.");
        }

        // Ensure queryBuilder is initialized
        if (queryBuilder == null) {
            queryBuilder = new StringBuilder();
        }

        // Start building the query
        queryBuilder.append(GROUP_BY)
                .append(SPACE);

        // Convert Column[] to String[]
        String[] columnNames = new String[columns.length];
        for (int i = 0; i < columns.length; i++) {
            columnNames[i] = columns[i].getFullName(); // Assuming Column has getColumnName() method
        }

        // Join column names with ", "
        queryBuilder.append(String.join(COMMA + SPACE, columnNames));
        queryBuilder.append(SPACE);

        return this;
    }

    public Query having(String condition) {
        queryBuilder.append(HAVING).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query ifNull(Column column, Object nullValue) {
        queryBuilder.append(IF_NULL).append(BRACKET_LEFT).append(column.getFullName()).append(COMMA).append(SPACE).append(nullValue).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }
    public Query ifNull(String column, Object nullValue) {
        queryBuilder.append(IF_NULL).append(BRACKET_LEFT).append(column).append(COMMA).append(SPACE).append(nullValue).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query in(Column[] columns) {
        if (columns == null || columns.length == 0) {
            throw new IllegalArgumentException("Columns array must not be null or empty.");
        }

        // Ensure queryBuilder is initialized
        if (queryBuilder == null) {
            queryBuilder = new StringBuilder();
        }

        // Start building the query
        queryBuilder.append(IN)
                .append(BRACKET_LEFT);

        // Convert Column[] to String[]
        String[] columnNames = new String[columns.length];
        for (int i = 0; i < columns.length; i++) {
            columnNames[i] = columns[i].getFullName(); // Assuming Column has getColumnName() method
        }

        // Join column names with ", "
        queryBuilder.append(String.join(COMMA + SPACE, columnNames));
        queryBuilder.append(BRACKET_RIGHT);

        return this;
    }

    public Query innerJoin(Table table) {
        queryBuilder.append(INNER_JOIN).append(SPACE).append(table.getTableName()).append(SPACE);
        return this;
    }
    public Query innerJoin(String table) {
        queryBuilder.append(INNER_JOIN).append(SPACE).append(table).append(SPACE);
        return this;
    }
    public Query insertIgnoreInto(Table table, Column[] columns) {
        if (columns == null || columns.length == 0) {
            throw new IllegalArgumentException("Columns array must not be null or empty.");
        }

        // Ensure queryBuilder is initialized
        if (queryBuilder == null) {
            queryBuilder = new StringBuilder();
        }

        // Start building the query
        queryBuilder.append(INSERT_IGNORE_INTO)
                .append(SPACE)
                .append(table.getTableName())
                .append(SPACE)
                .append(BRACKET_LEFT);

        // Convert Column[] to String[]
        String[] columnNames = new String[columns.length];
        for (int i = 0; i < columns.length; i++) {
            columnNames[i] = columns[i].getFullName(); // Assuming Column has getColumnName() method
        }

        // Join column names with ", "
        queryBuilder.append(String.join(COMMA + SPACE, columnNames));
        queryBuilder.append(SPACE)
                .append(BRACKET_RIGHT);

        return this;
    }

    public Query insertInto(Table table, Column columns) {
        queryBuilder.append(INSERT_INTO).append(SPACE).append(table.getTableName()).append(SPACE).append(BRACKET_LEFT).append(columns.getFullName()).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query insertInto(String table, String columns) {
        queryBuilder.append(INSERT_INTO).append(SPACE).append(table).append(SPACE).append(BRACKET_LEFT).append(columns).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query insertInto(Table table, Column[] columns) {
        if (columns == null || columns.length == 0) {
            throw new IllegalArgumentException("Columns array must not be null or empty.");
        }

        // Ensure queryBuilder is initialized
        if (queryBuilder == null) {
            queryBuilder = new StringBuilder();
        }

        // Start building the query
        queryBuilder.append(INSERT_INTO)
                .append(SPACE)
                .append(table.getTableName())
                .append(SPACE)
                .append(BRACKET_LEFT);

        // Convert Column[] to String[]
        String[] columnNames = new String[columns.length];
        for (int i = 0; i < columns.length; i++) {
            columnNames[i] = columns[i].getFullName(); // Assuming Column has getColumnName() method
        }

        // Join column names with ", "
        queryBuilder.append(String.join(COMMA + SPACE, columnNames));
        queryBuilder.append(SPACE)
                .append(BRACKET_RIGHT);

        return this;
    }


    public Query isNotNull(Column column) {
        queryBuilder.append(column.getFullName()).append(SPACE).append(IS_NOT_NULL).append(SPACE);
        return this;
    }

    public Query isNull(Column column) {
        queryBuilder.append(column.getFullName()).append(SPACE).append(IS_NULL).append(SPACE);
        return this;
    }

    public Query join(Table table) {
        queryBuilder.append(JOIN).append(SPACE).append(table.getTableName()).append(SPACE);
        return this;
    }
    public Query join(String table) {
        queryBuilder.append(JOIN).append(SPACE).append(table).append(SPACE);
        return this;
    }

    public Query leftBracket() {
        queryBuilder.append(SPACE).append(BRACKET_LEFT);
        return this;
    }

    public Query leftBracket(String value) {
        queryBuilder.append(BRACKET_LEFT).append(value).append(SPACE);
        return this;
    }

    public Query leftBracket(Column value) {
        queryBuilder.append(BRACKET_LEFT).append(value.getFullName()).append(SPACE);
        return this;
    }
    public Query leftBracket(Table value) {
        queryBuilder.append(BRACKET_LEFT).append(value.getTableName()).append(SPACE);
        return this;
    }

    public Query leftJoin(Table table) {
        queryBuilder.append(LEFT_JOIN).append(SPACE).append(table.getTableName()).append(SPACE);
        return this;
    }

    public Query leftJoin(String table) {
        queryBuilder.append(LEFT_JOIN).append(SPACE).append(table).append(SPACE);
        return this;
    }

    public Query less() {
        queryBuilder.append(LESS).append(SPACE);
        return this;
    }

    public Query less(int num) {
        queryBuilder.append(LESS).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query less(String condition) {
        queryBuilder.append(LESS).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query lessEquals() {
        queryBuilder.append(LESS_EQUALS).append(SPACE);
        return this;
    }

    public Query lessEquals(int num) {
        queryBuilder.append(LESS_EQUALS).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query lessEquals(String condition) {
        queryBuilder.append(LESS_EQUALS).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query like() {
        queryBuilder.append(LIKE).append(SPACE);
        return this;
    }

    public Query like(String condition) {
        queryBuilder.append(LIKE).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query limit(int limit) {
        queryBuilder.append(LIMIT).append(SPACE).append(limit).append(SPACE);
        return this;
    }

    public Query lineBreak() {
        queryBuilder.append(LINE_BREAK);
        return this;
    }

    public Query max(Column column) {
        queryBuilder.append(MAX).append(BRACKET_LEFT).append(column.getFullName()).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }
    public Query max(String column) {
        queryBuilder.append(MAX).append(BRACKET_LEFT).append(column).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query min(Column column) {
        queryBuilder.append(MIN).append(BRACKET_LEFT).append(column.getFullName()).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }
    public Query min(String column) {
        queryBuilder.append(MIN).append(BRACKET_LEFT).append(column).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query minus() {
        queryBuilder.append(MINUS).append(SPACE);
        return this;
    }

    public Query minus(int num) {
        queryBuilder.append(MINUS).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query notBetween(Column column, Object value1, Object value2) {
        queryBuilder.append(column.getFullName()).append(SPACE).append(NOT_BETWEEN).append(SPACE).append(value1).append(SPACE).append(AND).append(SPACE).append(value2).append(SPACE);
        return this;
    }

    public Query notEquals() {
        queryBuilder.append(NOT_EQUALS).append(SPACE).append(VARIABEL).append(SPACE);
        return this;
    }

    public Query notEquals(int num) {
        queryBuilder.append(NOT_EQUALS).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query notEquals(String condition) {
        queryBuilder.append(NOT_EQUALS).append(SPACE).append(condition).append(SPACE);
        return this;
    }
    public Query notEquals(Column condition) {
        queryBuilder.append(NOT_EQUALS).append(SPACE).append(condition.getFullName()).append(SPACE);
        return this;
    }

    public Query nullSQL() {
        queryBuilder.append(NULL).append(SPACE);
        return this;
    }

    public Query offset(int offset) {
        queryBuilder.append(OFFSET).append(SPACE).append(offset).append(SPACE);
        return this;
    }

    public Query on() {
        queryBuilder.append(ON).append(SPACE);
        return this;
    }

    public Query on(String value) {
        queryBuilder.append(ON).append(SPACE).append(value).append(SPACE);
        return this;
    }
    public Query on(Column value) {
        queryBuilder.append(ON).append(SPACE).append(value.getFullName()).append(SPACE);
        return this;
    }

    public Query or() {
        queryBuilder.append(OR).append(SPACE);
        return this;
    }

    public Query or(String condition) {
        queryBuilder.append(OR).append(SPACE).append(condition).append(SPACE);
        return this;
    }
    public Query or(Column condition) {
        queryBuilder.append(OR).append(SPACE).append(condition.getFullName()).append(SPACE);
        return this;
    }

    public Query orderBy() {
        queryBuilder.append(ORDER_BY).append(SPACE);
        return this;
    }

    public Query orderBy(String columns) {
        queryBuilder.append(ORDER_BY).append(SPACE).append(columns).append(SPACE);
        return this;
    }
    public Query orderBy(Column columns) {
        queryBuilder.append(ORDER_BY).append(SPACE).append(columns.getFullName()).append(SPACE);
        return this;
    }
    public Query orderBy(String[] columns) {
        if (columns == null || columns.length == 0) {
            throw new IllegalArgumentException("Columns array must not be null or empty.");
        }

        queryBuilder.append(ORDER_BY).append(SPACE);
        queryBuilder.append(String.join(COMMA + SPACE, columns));
        queryBuilder.append(SPACE);
        return this;
    }
    public Query orderBy(Column[] columns) {
        if (columns == null || columns.length == 0) {
            throw new IllegalArgumentException("Columns array must not be null or empty.");
        }

        // Ensure queryBuilder is initialized
        if (queryBuilder == null) {
            queryBuilder = new StringBuilder();
        }

        // Start building the query
        queryBuilder.append(ORDER_BY)
                .append(SPACE);

        // Convert Column[] to String[]
        String[] columnNames = new String[columns.length];
        for (int i = 0; i < columns.length; i++) {
            columnNames[i] = columns[i].getFullName(); // Assuming Column has getColumnName() method
        }

        // Join column names with ", "
        queryBuilder.append(String.join(COMMA + SPACE, columnNames));
        queryBuilder.append(SPACE);

        return this;
    }
    public Query plus() {
        queryBuilder.append(PLUS).append(SPACE);
        return this;
    }

    public Query plus(int num) {
        queryBuilder.append(PLUS).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query rightBracket() {
        queryBuilder.append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query rightBracket(String value) {
        queryBuilder.append(BRACKET_RIGHT).append(value).append(SPACE);
        return this;
    }

    public Query rightJoin(Table table) {
        queryBuilder.append(RIGHT_JOIN).append(SPACE).append(table.getTableName()).append(SPACE);
        return this;
    }
    public Query rightJoin(String table) {
        queryBuilder.append(RIGHT_JOIN).append(SPACE).append(table).append(SPACE);
        return this;
    }

    public Query select() {
        queryBuilder.append(SELECT).append(SPACE);
        return this;
    }
    public Query select(int num) {
        queryBuilder.append(SELECT).append(SPACE).append(num).append(SELECT);
        return this;
    }

    public Query select(Column columns) {
        queryBuilder.append(SELECT).append(SPACE).append(columns.getFullName()).append(SPACE);
        return this;
    }
    public Query select(String columns) {
        queryBuilder.append(SELECT).append(SPACE).append(columns).append(SPACE);
        return this;
    }

    public Query select(String[] columns) {
        if (columns == null || columns.length == 0) {
            throw new IllegalArgumentException("Columns array must not be null or empty.");
        }

        queryBuilder.append(SELECT).append(SPACE);
        queryBuilder.append(String.join(COMMA + SPACE, columns));
        queryBuilder.append(SPACE);
        return this;
    }

    public Query select(Column[] columns) {
        if (columns == null || columns.length == 0) {
            throw new IllegalArgumentException("Columns array must not be null or empty.");
        }

        // Ensure queryBuilder is initialized
        if (queryBuilder == null) {
            queryBuilder = new StringBuilder();
        }

        // Start building the query
        queryBuilder.append(SELECT)
                .append(SPACE);

        // Convert Column[] to String[]
        String[] columnNames = new String[columns.length];
        for (int i = 0; i < columns.length; i++) {
            columnNames[i] = columns[i].getFullName(); // Assuming Column has getColumnName() method
        }

        // Join column names with ", "
        queryBuilder.append(String.join(COMMA + SPACE, columnNames));
        queryBuilder.append(SPACE);

        return this;
    }

    public Query selectAll() {
        queryBuilder.append(SELECT_ALL).append(SPACE);
        return this;
    }

    public Query selectDistinct() {
        queryBuilder.append(SELECT).append(SPACE).append(DISTINCT).append(SPACE);
        return this;
    }
    public Query selectDistinct(Column column) {
        queryBuilder.append(SELECT).append(SPACE).append(DISTINCT).append(SPACE).append(column.getFullName()).append(SPACE);
        return this;
    }

    public Query set(String condition) {
        queryBuilder.append(SET).append(SPACE).append(condition).append(SPACE);
        return this;
    }
    public Query set(Column condition) {
        queryBuilder.append(SET).append(SPACE).append(condition.getFullName()).append(SPACE);
        return this;
    }

    public Query str(String s) {
        queryBuilder.append(s).append(SPACE);
        return this;
    }
    public Query str(Column s) {
        queryBuilder.append(s.getFullName()).append(SPACE);
        return this;
    }

    public Query str(int num) {
        queryBuilder.append(num).append(SPACE);
        return this;
    }

    public Query sum() {
        queryBuilder.append(SUM);
        return this;
    }

    public Query sum(Column column) {
        queryBuilder.append(SUM).append(BRACKET_LEFT).append(column.getFullName()).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }
    public Query sum(String column) {
        queryBuilder.append(SUM).append(BRACKET_LEFT).append(column).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query then() {
        queryBuilder.append(THEN).append(SPACE);
        return this;
    }

    public Query then(String condition) {
        queryBuilder.append(THEN).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query then(int num) {
        queryBuilder.append(THEN).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query times() {
        queryBuilder.append(TIMES).append(SPACE);
        return this;
    }

    public Query times(int num) {
        queryBuilder.append(TIMES).append(SPACE).append(num).append(SPACE);
        return this;
    }

    public Query union() {
        queryBuilder.append(UNION).append(SPACE);
        return this;
    }

    public Query unionAll() {
        queryBuilder.append(UNION).append(SPACE).append(ALL).append(SPACE);
        return this;
    }

    public Query update(Table table) {
        queryBuilder.append(UPDATE).append(SPACE).append(table.getTableName()).append(SPACE);
        return this;
    }
    public Query update(String table) {
        queryBuilder.append(UPDATE).append(SPACE).append(table).append(SPACE);
        return this;
    }

    public Query values() {
        queryBuilder.append(VALUES).append(SPACE).append(BRACKET_LEFT);
        return this;
    }

    public Query values(int count) {
        if (count <= 0) {
            throw new IllegalArgumentException("Count must be greater than zero.");
        }

        queryBuilder.append(VALUES).append(SPACE).append(BRACKET_LEFT);

        for (int i = 0; i < count; i++) {
            queryBuilder.append(VARIABEL);

            if (i < count - 1) {
                queryBuilder.append(COMMA).append(SPACE);
            }
        }

        queryBuilder.append(BRACKET_RIGHT).append(SPACE);

        return this;
    }

    public Query values(Column columns) {
        queryBuilder.append(VALUES).append(SPACE).append(BRACKET_LEFT).append(columns.getFullName()).append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query values(String[] values) {
        if (values.length == 0) {
            throw new IllegalArgumentException("Attributes and values arrays must have the same length and cannot be empty.");
        }

        queryBuilder.append(VALUES).append(BRACKET_LEFT);
        queryBuilder.append("\"").append(values[0]).append("\"");
        for (int i = 1; i < values.length; i++) {
            queryBuilder.append(COMMA).append("\"").append(values[i]).append("\"");
        }


        queryBuilder.append(BRACKET_RIGHT).append(SPACE);
        return this;
    }

    public Query variabel() {
        queryBuilder.append(VARIABEL).append(SPACE);
        return this;
    }

    public Query when() {
        queryBuilder.append(WHEN).append(SPACE);
        return this;
    }

    public Query when(String condition) {
        queryBuilder.append(WHEN).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query where() {
        queryBuilder.append(WHERE).append(SPACE);
        return this;
    }
    public Query where(String condition) {
        queryBuilder.append(WHERE).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query where(int condition) {
        queryBuilder.append(WHERE).append(SPACE).append(condition).append(SPACE);
        return this;
    }

    public Query where(Column condition) {
        queryBuilder.append(WHERE).append(SPACE).append(condition.getFullName()).append(SPACE);
        return this;
    }

    public Query where(String[] attributes, String[] values) {
        if (attributes.length != values.length || attributes.length == 0) {
            throw new IllegalArgumentException("Attributes and values arrays must have the same length and cannot be empty.");
        }

        queryBuilder.append(WHERE).append(SPACE);

        if (attributes.length == 1) {
            queryBuilder.append(attributes[0]).append(EQUALS).append("\"").append(values[0]).append("\"");
        } else {
            queryBuilder.append(attributes[0]).append("\"").append(EQUALS).append(values[0]).append("\"");
            for (int i = 1; i < attributes.length; i++) {
                queryBuilder.append(AND).append(attributes[i]).append(EQUALS).append("\"").append(values[i]).append("\"");
            }
        }

        queryBuilder.append(SPACE);
        return this;
    }

    public String build() {
        String query = queryBuilder.toString();
        if(!query.contains(";")){
            query = queryBuilder.append(";").toString();
        }
        return query.replace(" (", "(").replace(" )", ")").replace(" ,", ", ").replace("  "," ");
    }


}
Wozu?!?


Das gibt konzeptionell schon keinen Sinn. Eingebettet werden Objekte, nicht Spalten. Und Objekte haben Attribute, keine Spalten. Die Attribute werden auf Spalten der DB abgebildet.

Allerdings weiß ich nicht, was das eigentlich werden soll, wenn es fertig ist. Jede DB kennt ihre Spalten, was willst Du das nochmal speichern?
Ich bin mit Hibernate eigentlich unzufrieden, da es nicht meinen Wünschen entspricht und würde mir gernewas komplett neues erstellen, was auf keinem Framework oder einer fremden Bibliothek basiert.
 

MJannek

Bekanntes Mitglied
Ich suche einen Ansatz, wie ich Klassen als DB-Tabellen umsetzen kann (durch Annotations, Erweiterung anderer selbsterstellter Klassen bzw. Interfaces, etc). Ich möchte dabei keine Frameworks, oder zusätzlich Bibliotheken verwenden (außer dem mysql connector). Außerdem sollen die Änderungen in Klassendefinitionen beim nächsten Programmstart auf die DB übertragen werden. Queries sollen in etwas wie folgt aussehen und nicht durch Strings dargestellt werden.
Java:
User.objects.filter(status_id__gt=1);
Vielen Dank im voraus für die Tipps.

PS.: Ich weiß, dass ich mir das alles selbst erstellen muss und es wahrscheinlich sehr aufwendig ist.
 

Marinek

Bekanntes Mitglied
Ja. Das macht alles JPA mit Hibernate.

Das nicht zu verwenden und selbst zu implementieren ist, wie du sagst extrem aufwändig und eben doppelte Implementierung.

Queries sollen in etwas wie folgt aussehen und nicht durch Strings dargestellt werden.
Java:
User.objects.filter(status_id__gt=1);
Vielen Dank im voraus für die Tipps

Dann kommt hinzu, dass man das so mit Java nicht 1:1 hinbekommen wird, weil es in Java diese Sprachkonstrukte filter(status_id__gt=1); nicht gibt.

Die Hibernate Query API macht genau das. Und Spring Data (Kommt später im Text) macht es noch besser. Beachte das Posting #28.

Wenn du DDLs direkt aus den annotierten Klassen verwenden willst, dann wird das in kleinen Projekten in denen sich wenig ändert auch funktionieren.

Aber in Enterprise Projekten kommt diese Funktion an ihre Grenzen.

Beispiel, dass mir so ad hoc einfällt: Ein Feld wird zwischen Tabellen verschoben.

Da wird Hibernate oder deine Implementierung nicht schlau genug sein das zu erkennen und die Daten entsprechend verschieben.

Und das ist ein BIG Issue in Enterprise Anwendungen, das da auf dich zukommen.

Da du aber immernoch nicht gesagt hast, warum Du das genau so und nicht anders haben willst oder was Du da genau fachlich machst, kann ich nur Zusammenfassend die folgenden Tipps geben:

- Ist es ein privates Projekt: Mach und lerne. Es ist wichtig hinter die Funktionsweisen von ORM Frameworks zu blicken, um diese richtig einsetzen zu können.

- Ist es ein Enterprise Projekt: Lass es. Das Projekt wird viel zu teuer. Aufwändig in der Wartung und man wird hinsichtlich Sicherheit und Fehlertolleranz garantiert nicht an Hibernate ran kommen.

- Schaue dir lieber Spring an. Dort sind höhere APIs vorhanden, die die meisten Businessfälle aus einer Hand abdecken werden.

- Schaue dir Liquibase an. Und nutze das für DDL und generiere Liquibase XMLs beim Bauen aus den Annotationen.

Bitte beschreibe hier deutlicher fachlich was du tust. Oder stelle konkrete Fragen.

Gruß
Martin
 

KonradN

Super-Moderator
Mitarbeiter
Also die Frage ist wirklich, was Du im Detail benötigst bzw. was Dir bei JPA / Hibernate fehlt.

a) Ggf. gibt es ja bereits andere Bibliotheken, die Dir sowas bieten?
b) Evtl. kann man das vorhandene Nutzen und ergänzen?

Jetzt kommen paar Möglichkeiten, aber nur die reine Erwähnung heisst nicht, dass es (für Dich) Sinn macht. Die Aussagen von @Marinek in #38 solltest Du gut lesen und bedenken!

Wenn man neue Konstrukte entwickeln möchte, dann muss man sich natürlich an die Java Syntax halten. Und da kann man sich dann überlegen, was man bauen möchte. Schon bei User.objects.... wird es ggf. schwierig. Das könnte man ggf. bauen über eine Entity Klasse, von der alle erben müssten um dann kannst Du sehr viel selbst bauen.
filter könnte z.B. genau so aufgebaut werden, wie bei Streams, die da halt ein Predicate<? super T> als Parameter nehmen. Dann wäre es halt eher etwas wie filter( u -> u.status_id_gt = 1).
==> Aber das status_id_gt sieht nach einem Column aus und nicht nach einem Feld. statusIdGt oder so wäre ja vermutlich dann das Feld bzw. wenn das eine id zu einer anderen Entity/Tabelle ist, dann wäre es direkt eine Referenz darauf.
==> Als Entwickler will man im Java Code doch auf der Java Ebene entwickeln und nicht auf der Datenbankebene. Das wird daher auch bei der Angabe von Queries berücksichtigt. Die Möglichkeit von SQL (native) Queries ist natürlich auch gegeben, aber da wäre ich vorsichtig mit der Nutzung. Also Wenn ich ein Feld habe mit @Column(name = ...) und da dann etwas ändere, dann breche ich den Code an anderer Stelle, der als native Query die Abfrage macht. Nutze ich den Feldnamen, dann habe ich deutlich mehr Chancen auf Refactoring Unterstützung und Compile-Zeit.

Wenn Du da eigene Dinge bauen willst, dann geht das natürlich auch. ChatGPT erstellt Dir gerne Code um Entities auszuwerten. Das kann man klein anfangen mit @Column Einträgen. Dann kann man dein @Embedded mit nutzen und das dann nach und nach immer weiter erweitern.
(Ich selbst habe das schon einmal gemacht, weil ich halt JPA Entities vorliegen hatte und nutzen wollte. Nur eben war das Ziel, dass ich BULK INSERT Skripte generieren musste und das Zielsystem unter aktiver Entwicklung ist und ständig geändert wird. Und die Änderungen wollte ich zur Compile-Zeit haben und nicht erst bei Integration-Tests. Also wurden die Entities ausgewertet und dann habe ich z.B. eine Klasse InsertStatement geschrieben, der ich dann halt Feldnamen mit Werten gegeben habe)

Das eigene Lesen kann man sich dann auch überlegen. Da wäre dann z.B. bei filter die andere Idee, dass man es als String übergibt. Also filter("status_id_gt = 1"). Das kann man dann 1:1 nehmen und in eine WHERE Bedingung setzen. Ggf. mit einem Parser, der das etwas prüft.
Ich hatte den Code zum Lesen der Entitäten selbst geschrieben - aber das kann man natürlich auch generieren. Das kann dynamisch (einmalig) erfolgen so dass man da nicht langsame Reflection verwenden müsste. Das ist also auch erst einmal kein Thema. Das wird aber schnell deutlich komplexer, sobald man halt referenzierte Entitäten berücksichtigen möchte und so ...

Also ganz klar: Ja, sowas kann man sich bauen. Das ist von der Komplexität nicht einmal so groß, so man sich bei der Funktionalität stark/etwas einschränken kann. Als Spielerei: Kein Thema. Wie gesagt: Spiel mal mit ChatGPT herum!

Die Idee, Datenbank-Schematas automatisch anzupassen halte ich für sehr problematisch. Du musst halt immer schauen, was mit den Daten passieren soll. Einfache Operationen wie ein Delete oder Add sind ok. Typanpassungen sind aber schon problematisch, weil da Datenverlust entstehen kann. Renames muss man erst einmal als solche erkennen ...
Aber davon unabhängig: Die Datenbank lässt sich über die JDBC Metadaten sehr gut auslesen und auswerten. Um dann halt notwendige Abweichungen zu erkennen. Hier kann eine Idee ja auch sein, dass man nur Change Skripts erzeugt, die dann abgelegt werden. Man gibt dann dem Entwickler die Möglichkeit, diese anzupassen. Und dann würde man die Change-Skripte nur noch automatisiert anwenden. (Aber selbst diese Anwendung von Change-Skripten kann schon eine komplexere Sache werden. Viele Datenbanken haben Möglichkeiten wie Snapshots - das könnte sinnvoll sein. Und auch die Möglichkeit, alles in einer Transaktion oder in vielen Transaktionen zu machen. (Was will man zurück rollen? Alles? Nur das letzte Schema Update, das fehlgeschlagen ist? .... Error Reporting und Auswertungen ist auch ein wichtiges Thema wenn es um produktive, wichtige Daten geht...
 

KonradN

Super-Moderator
Mitarbeiter
Und dann auch einfach einmal die Frage zwischendurch: Hast Du Dir mal JOOQ angesehen? Das ist dann kein JPA mehr und Du hast die Möglichkeit, SQL Queries in Java zu schreiben. Das Beispiel von der Homepage https://www.jooq.org/ ist z.B.

Java:
create.select(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, count())
      .from(AUTHOR)
      .join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID))
      .where(BOOK.LANGUAGE.eq("DE"))
      .and(BOOK.PUBLISHED.gt(date("2008-01-01")))
      .groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)
      .having(count().gt(5))
      .orderBy(AUTHOR.LAST_NAME.asc().nullsFirst())
      .limit(2)
      .offset(1)

für ein SQL Statement
SQL:
SELECT AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, COUNT(*)
FROM AUTHOR
JOIN BOOK ON AUTHOR.ID = BOOK.AUTHOR_ID
WHERE BOOK.LANGUAGE = 'DE'
AND BOOK.PUBLISHED > DATE '2008-01-01'
GROUP BY AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME
HAVING COUNT(*) > 5
ORDER BY AUTHOR.LAST_NAME ASC NULLS FIRST
LIMIT 2
OFFSET 1

Ich weiss nicht, was Du exakt erwartest / brauchst, daher das nur als kleine Anregung.
 

MJannek

Bekanntes Mitglied
Vielen Dank. So etwas wie @KonradN in Podt #40 beschrieben hat, habe ich gesucht.
Und dann auch einfach einmal die Frage zwischendurch: Hast Du Dir mal JOOQ angesehen? Das ist dann kein JPA mehr und Du hast die Möglichkeit, SQL Queries in Java zu schreiben. Das Beispiel von der Homepage https://www.jooq.org/ ist z.B.

Java:
create.select(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, count())
      .from(AUTHOR)
      .join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID))
      .where(BOOK.LANGUAGE.eq("DE"))
      .and(BOOK.PUBLISHED.gt(date("2008-01-01")))
      .groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)
      .having(count().gt(5))
      .orderBy(AUTHOR.LAST_NAME.asc().nullsFirst())
      .limit(2)
      .offset(1)

für ein SQL Statement
SQL:
SELECT AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, COUNT(*)
FROM AUTHOR
JOIN BOOK ON AUTHOR.ID = BOOK.AUTHOR_ID
WHERE BOOK.LANGUAGE = 'DE'
AND BOOK.PUBLISHED > DATE '2008-01-01'
GROUP BY AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME
HAVING COUNT(*) > 5
ORDER BY AUTHOR.LAST_NAME ASC NULLS FIRST
LIMIT 2
OFFSET 1

Ich weiss nicht, was Du exakt erwartest / brauchst, daher das nur als kleine Anregung.
 

Oneixee5

Top Contributor
Vielen Dank. So etwas wie @KonradN in Podt #40 beschrieben hat, habe ich gesucht.
Ich finde JOOQ viel zu umständlich und zu viel Code - ich kann mich auch nicht erinnern (deine Anforderung), dass man damit die DB(DDL) ändern kann. Allerdings habe ich es lange nicht verwendet. Außerdem wolltest du auch keine zusätzlichen Bibliotheken verwenden.
MySQL als Datenbank zu bezeichnen, ist auch sehr großzügig.
 

MJannek

Bekanntes Mitglied
Ich habe mich jetzt doch mit Hibernate abgefunden, habe jetzt aber folgendes Problem:
Java:
package org.mjannek.database.dialect;

import org.hibernate.dialect.MySQLDialect;

public class MySQLMyISAMDialect extends MySQLDialect {

    @Override
    public String getTableTypeString() {
        return " ENGINE=MyISAM";
    }
}

Java:
package org.mjannek.database;

import javax.persistence.*;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.reflections.*;

public class HibernateUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();


    private static SessionFactory buildSessionFactory() {
        try {
            Configuration configuration = new Configuration();
            configuration.configure();

            // Automatische Erkennung aller Entitäten im Paket
            Reflections reflections = new Reflections("org.mjannek.sport.buli.tables");
            for (Class<?> clazz : reflections.getTypesAnnotatedWith(Entity.class)) {
                configuration.addAnnotatedClass(clazz);
            }

            return configuration.buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public static void shutdown() {
        getSessionFactory().close();
    }
}

Java:
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- JDBC Database connection settings -->
        <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://server:3306/schema</property>
        <property name="hibernate.connection.username">user</property>
        <property name="hibernate.connection.password">pw</property>

        <!-- JDBC connection pool settings -->
        <property name="hibernate.c3p0.min_size">5</property>
        <property name="hibernate.c3p0.max_size">20</property>
        <property name="hibernate.c3p0.timeout">300</property>
        <property name="hibernate.c3p0.max_statements">50</property>
        <property name="hibernate.c3p0.idle_test_period">3000</property>

        <!-- Specify custom dialect -->
        <property name="hibernate.dialect">org.mjannek.database.dialect.MySQLMyISAMDialect</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="hibernate.show_sql">true</property>

        <!-- Schema generation strategy -->
        <property name="hibernate.hbm2ddl.auto">update</property>

        <!-- Automatic detection of annotated entities -->
        <property name="hibernate.archive.autodetection">class,hbm</property>
    </session-factory>
</hibernate-configuration>

Java:
package org.mjannek.sport.buli.tables;

import java.time.*;
import javax.persistence.*;
import org.mjannek.database.entity.*;

@Entity
@Table(name = "clubs", uniqueConstraints = {
        @UniqueConstraint(columnNames = "link"),
        @UniqueConstraint(columnNames = "longname")
})
public class Club extends BaseEntity {


    @Column(name = "longname", nullable = false, length = 255)
    private String longname;


    @Column(name = "shortname", nullable = false, length = 3)
    private String shortname;


    @Column(name = "foreground", length = 8)
    private String foreground;


    @Column(name = "background", length = 7)
    private String background;


    @Column(name = "foundingdate")
    private LocalDate foundingdate;


    @Column(name = "info", columnDefinition = "TEXT")
    private String info;


    @Column(name = "name", nullable = false, length = 255)
    private String name;


    @Column(name = "city", columnDefinition = "TEXT")
    private String city;


    @Column(name = "fullname", columnDefinition = "TEXT")
    private String fullname;


    @Column(name = "link", length = 255)
    private String link;

    // No-arg constructor for JPA
    public Club() {
        super();
    }

    // Constructor for setting id
    public Club(int id) {
        super(id);
    }

    // Getters and Setters
    public String getLongname() {
        return longname;
    }

    public void setLongname(String longname) {
        this.longname = longname;
    }

    public String getShortname() {
        return shortname;
    }

    public void setShortname(String shortname) {
        this.shortname = shortname;
    }

    public String getForeground() {
        return foreground;
    }

    public void setForeground(String foreground) {
        this.foreground = foreground;
    }

    public String getBackground() {
        return background;
    }

    public void setBackground(String background) {
        this.background = background;
    }

    public LocalDate getFoundingdate() {
        return foundingdate;
    }

    public void setFoundingdate(LocalDate foundingdate) {
        this.foundingdate = foundingdate;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getFullname() {
        return fullname;
    }

    public void setFullname(String fullname) {
        this.fullname = fullname;
    }

    public String getLink() {
        return link;
    }

    public void setLink(String link) {
        this.link = link;
    }
}

Java:
package org.mjannek.database.entity;

import javax.persistence.*;

@MappedSuperclass
public abstract class BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    public BaseEntity() {
        // Default-Konstruktor
    }

    public BaseEntity(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTableName() {
        Table tableAnnotation = getClass().getAnnotation(Table.class);
        String tableName;

        if (tableAnnotation != null) {
            tableName = tableAnnotation.name(); // Name aus der Annotation
        } else {
            // Fallback, falls @Table nicht vorhanden ist
            tableName = getClass().getSimpleName();
        }
        return tableName;
    }
}
Code:
plugins {
    id("java")
}

group = "org.mjannek"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.hibernate:hibernate-core:5.+")
    implementation("org.reflections:reflections:0.10.2")
    implementation("ch.qos.logback:logback-classic:1.2.3")
    implementation("mysql:mysql-connector-java:8.+")
    implementation("javax.persistence:javax.persistence-api:2.2")
    implementation("org.jsoup:jsoup:1.18.3")
    implementation("com.sun.mail:javax.mail:1.6.2")
    implementation("com.mchange:c3p0:0.9.5.5")
    testImplementation(platform("org.junit:junit-bom:5.10.0"))
    testImplementation("org.junit.jupiter:junit-jupiter")
}

tasks.test {
    useJUnitPlatform()
}

Club ist eine meiner Entities.
Ich erhalte folgende Fehlermeldung:
Execution failed for task 'org.mjannek.database.EntityFinder.main()'.
Process 'command 'C:\Program Files\Java\jdk-23\bin\java.exe'' finished with non-zero exit value 1

* Try:
Run with --stacktrace option to get the stack trace.
Run with --info or --debug option to get more log output.
Run with --scan to get full insights.
Get more help at https://help.gradle.org.
BUILD FAILED in 10s
3 actionable tasks: 2 executed, 1 up-to-date
 

Oneixee5

Top Contributor
Selbst wenn das, was du da willst gehen würde, was nicht geht, weil man keine Annotationen in Java vererben kann, könnte Hibernate damit nicht umgehen.
 
Zuletzt bearbeitet:

MJannek

Bekanntes Mitglied
Ich habe mich jetzt doch mit Hibernate abgefunden, habe jetzt aber folgendes Problem:
Java:
package org.mjannek.database.dialect;

import org.hibernate.dialect.MySQLDialect;

public class MySQLMyISAMDialect extends MySQLDialect {

    @Override
    public String getTableTypeString() {
        return " ENGINE=MyISAM";
    }
}

Java:
package org.mjannek.database;

import javax.persistence.*;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.reflections.*;

public class HibernateUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();


    private static SessionFactory buildSessionFactory() {
        try {
            Configuration configuration = new Configuration();
            configuration.configure();

            // Automatische Erkennung aller Entitäten im Paket
            Reflections reflections = new Reflections("org.mjannek.sport.buli.tables");
            for (Class<?> clazz : reflections.getTypesAnnotatedWith(Entity.class)) {
                configuration.addAnnotatedClass(clazz);
            }

            return configuration.buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public static void shutdown() {
        getSessionFactory().close();
    }
}

Java:
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- JDBC Database connection settings -->
        <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://server:3306/schema</property>
        <property name="hibernate.connection.username">user</property>
        <property name="hibernate.connection.password">pw</property>

        <!-- JDBC connection pool settings -->
        <property name="hibernate.c3p0.min_size">5</property>
        <property name="hibernate.c3p0.max_size">20</property>
        <property name="hibernate.c3p0.timeout">300</property>
        <property name="hibernate.c3p0.max_statements">50</property>
        <property name="hibernate.c3p0.idle_test_period">3000</property>

        <!-- Specify custom dialect -->
        <property name="hibernate.dialect">org.mjannek.database.dialect.MySQLMyISAMDialect</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="hibernate.show_sql">true</property>

        <!-- Schema generation strategy -->
        <property name="hibernate.hbm2ddl.auto">update</property>

        <!-- Automatic detection of annotated entities -->
        <property name="hibernate.archive.autodetection">class,hbm</property>
    </session-factory>
</hibernate-configuration>

Java:
package org.mjannek.sport.buli.tables;

import java.time.*;
import javax.persistence.*;
import org.mjannek.database.entity.*;

@Entity
@Table(name = "clubs", uniqueConstraints = {
        @UniqueConstraint(columnNames = "link"),
        @UniqueConstraint(columnNames = "longname")
})
public class Club extends BaseEntity {


    @Column(name = "longname", nullable = false, length = 255)
    private String longname;


    @Column(name = "shortname", nullable = false, length = 3)
    private String shortname;


    @Column(name = "foreground", length = 8)
    private String foreground;


    @Column(name = "background", length = 7)
    private String background;


    @Column(name = "foundingdate")
    private LocalDate foundingdate;


    @Column(name = "info", columnDefinition = "TEXT")
    private String info;


    @Column(name = "name", nullable = false, length = 255)
    private String name;


    @Column(name = "city", columnDefinition = "TEXT")
    private String city;


    @Column(name = "fullname", columnDefinition = "TEXT")
    private String fullname;


    @Column(name = "link", length = 255)
    private String link;

    // No-arg constructor for JPA
    public Club() {
        super();
    }

    // Constructor for setting id
    public Club(int id) {
        super(id);
    }

    // Getters and Setters
    public String getLongname() {
        return longname;
    }

    public void setLongname(String longname) {
        this.longname = longname;
    }

    public String getShortname() {
        return shortname;
    }

    public void setShortname(String shortname) {
        this.shortname = shortname;
    }

    public String getForeground() {
        return foreground;
    }

    public void setForeground(String foreground) {
        this.foreground = foreground;
    }

    public String getBackground() {
        return background;
    }

    public void setBackground(String background) {
        this.background = background;
    }

    public LocalDate getFoundingdate() {
        return foundingdate;
    }

    public void setFoundingdate(LocalDate foundingdate) {
        this.foundingdate = foundingdate;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getFullname() {
        return fullname;
    }

    public void setFullname(String fullname) {
        this.fullname = fullname;
    }

    public String getLink() {
        return link;
    }

    public void setLink(String link) {
        this.link = link;
    }
}

Java:
package org.mjannek.database.entity;

import javax.persistence.*;

@MappedSuperclass
public abstract class BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    public BaseEntity() {
        // Default-Konstruktor
    }

    public BaseEntity(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTableName() {
        Table tableAnnotation = getClass().getAnnotation(Table.class);
        String tableName;

        if (tableAnnotation != null) {
            tableName = tableAnnotation.name(); // Name aus der Annotation
        } else {
            // Fallback, falls @Table nicht vorhanden ist
            tableName = getClass().getSimpleName();
        }
        return tableName;
    }
}
Code:
plugins {
    id("java")
}

group = "org.mjannek"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.hibernate:hibernate-core:5.+")
    implementation("org.reflections:reflections:0.10.2")
    implementation("ch.qos.logback:logback-classic:1.2.3")
    implementation("mysql:mysql-connector-java:8.+")
    implementation("javax.persistence:javax.persistence-api:2.2")
    implementation("org.jsoup:jsoup:1.18.3")
    implementation("com.sun.mail:javax.mail:1.6.2")
    implementation("com.mchange:c3p0:0.9.5.5")
    testImplementation(platform("org.junit:junit-bom:5.10.0"))
    testImplementation("org.junit.jupiter:junit-jupiter")
}

tasks.test {
    useJUnitPlatform()
}

Club ist eine meiner Entities.
Ich erhalte folgende Fehlermeldung:
Execution failed for task 'org.mjannek.database.EntityFinder.main()'.


* Try:

BUILD FAILED in 10s
3 actionable tasks: 2 executed, 1 up-to-date
Hab den Fehler gefunden
 

MJannek

Bekanntes Mitglied
Es wäre sehr nett die Lösung zu schreiben. Für alle, die das lesen.
Statt:
Java:
public class EntityFinder {
    public static void main(String[] args) {
        Session session = HibernateUtil.getSessionFactory();
Transaction transaction = null;

try {
            transaction = session.beginTransaction();


}catch (Exception e){

        }
    }
}
muss man verwenden:
Java:
public class EntityFinder {
    public static void main(String[] args) {
        Session session = HibernateUtil.getSessionFactory().openSession();
Transaction transaction = null;

try {
            transaction = session.beginTransaction();


}catch (Exception e){

        }
    }
}
Ich hatte also vergessen, die Session zu öffnen
 

MJannek

Bekanntes Mitglied
Java:
package org.mjannek.database.entity;

import javax.persistence.*;

@MappedSuperclass
public abstract class BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    public BaseEntity() {
        // Default-Konstruktor
    }

    public BaseEntity(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTableName() {
        Table tableAnnotation = getClass().getAnnotation(Table.class);
        String tableName;

        if (tableAnnotation != null) {
            tableName = tableAnnotation.name(); // Name aus der Annotation
        } else {
            // Fallback, falls @Table nicht vorhanden ist
            tableName = getClass().getSimpleName();
        }
        return tableName;
    }
}

Ich habe mir das als Basis für jede Entität erstellt, da ich möchte, dass jede Tabelle eine Spalte ID hat. Könnte man in der Klasse noch etwas anderes hinzufügen? Außer Spalten createdAt oder UpdatedAt
 

MJannek

Bekanntes Mitglied
Ich ha
Java:
package org.mjannek.database.entity;

import javax.persistence.*;

@MappedSuperclass
public abstract class BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    public BaseEntity() {
        // Default-Konstruktor
    }

    public BaseEntity(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTableName() {
        Table tableAnnotation = getClass().getAnnotation(Table.class);
        String tableName;

        if (tableAnnotation != null) {
            tableName = tableAnnotation.name(); // Name aus der Annotation
        } else {
            // Fallback, falls @Table nicht vorhanden ist
            tableName = getClass().getSimpleName();
        }
        return tableName;
    }
}

Ich habe mir das als Basis für jede Entität erstellt, da ich möchte, dass jede Tabelle eine Spalte ID hat. Könnte man in der Klasse noch etwas anderes hinzufügen? Außer Spalten createdAt oder UpdatedAt
Ich habe BaseEntity jetzt schon selbst erweitert, und u.a. doch createdAt und UpdatedAt hinzugefügt.
Java:
package org.mjannek.database.entity;

import java.io.*;
import java.time.*;
import javax.persistence.*;
import java.sql.Timestamp;
import javax.persistence.ForeignKey;
import javax.persistence.Table;
import org.hibernate.annotations.*;
import org.mjannek.sport.buli.tables.*;

@MappedSuperclass
@FilterDef(name = "deletedFilter", parameters = @ParamDef(name = "isDeleted", type = "boolean"))
@Filter(name = "deletedFilter", condition = "deleted = :isDeleted")
public abstract class BaseEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "createdat", updatable = false, nullable = false)
    private Timestamp createdAt;

    @Column(name = "updatedat", nullable = false)
    private Timestamp updatedAt;

    @Column(name = "deleted", nullable = false)
    private Boolean deleted = false;

    @ManyToOne
    @JoinColumn(name = "createdby", updatable = false, foreignKey = @ForeignKey(name = "fk_baseentity_createdby"))
    private User createdBy;

    @ManyToOne
    @JoinColumn(name = "updatedby", foreignKey = @ForeignKey(name = "fk_baseentity_updatedby"))
    private User updatedBy;

    @Column(name = "deletedat")
    private Timestamp deletedAt;

    @ManyToOne
    @JoinColumn(name = "deletedby", foreignKey = @ForeignKey(name = "fk_baseentity_deletedby"))
    private User deletedBy;

    @Version
    private Integer version;

    // Basis-Konstruktor
    public BaseEntity() {
        // Initialisierung der Felder, falls nicht bereits gesetzt
        this.createdAt = Timestamp.valueOf(LocalDateTime.now());
        this.updatedAt = Timestamp.valueOf(LocalDateTime.now());
    }

    public BaseEntity(Integer id) {
        this.id = id;
        this.createdAt = Timestamp.valueOf(LocalDateTime.now());
        this.updatedAt = Timestamp.valueOf(LocalDateTime.now());
    }

    @PrePersist
    protected void onCreate() {
        this.createdAt = Timestamp.valueOf(LocalDateTime.now());
        this.updatedAt = Timestamp.valueOf(LocalDateTime.now());
    }

    @PreUpdate
    protected void onUpdate() {
        this.updatedAt = Timestamp.valueOf(LocalDateTime.now());
    }

    // Getter and Setter
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Timestamp getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Timestamp createdAt) {
        this.createdAt = createdAt;
    }

    public Timestamp getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(Timestamp updatedAt) {
        this.updatedAt = updatedAt;
    }

    public Boolean getDeleted() {
        return deleted;
    }

    public void setDeleted(Boolean deleted) {
        this.deleted = deleted;
    }

    public User getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(User createdBy) {
        this.createdBy = createdBy;
    }

    public User getUpdatedBy() {
        return updatedBy;
    }

    public void setUpdatedBy(User updatedBy) {
        this.updatedBy = updatedBy;
    }

    public Timestamp getDeletedAt() {
        return deletedAt;
    }

    public void setDeletedAt(Timestamp deletedAt) {
        this.deletedAt = deletedAt;
    }

    public User getDeletedBy() {
        return deletedBy;
    }

    public void setDeletedBy(User deletedBy) {
        this.deletedBy = deletedBy;
    }

    public Integer getVersion() {
        return version;
    }

    public void setVersion(Integer version) {
        this.version = version;
    }

    // Utility Methods
    public void markAsDeleted(User deletedByUser) {
        this.deleted = true;
        this.deletedAt = Timestamp.valueOf(LocalDateTime.now());
        this.deletedBy = deletedByUser;
    }

    public void restore() {
        this.deleted = false;
        this.deletedAt = null;
        this.deletedBy = null;
        this.updatedAt = Timestamp.valueOf(LocalDateTime.now());
    }
    public String getTableName() {
        // Überprüfen, ob die Annotation @Table vorhanden ist
        Table tableAnnotation = this.getClass().getAnnotation(Table.class);
        if (tableAnnotation != null) {
            return tableAnnotation.name(); // Gibt den Tabellennamen zurück
        }
        return this.getClass().getSimpleName(); // Fallback, falls keine @Table-Annotation vorhanden ist
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        BaseEntity that = (BaseEntity) o;
        return id != null && id.equals(that.id);
    }

    @Override
    public int hashCode() {
        return getClass().hashCode();
    }

    @Override
    public String toString() {
        return "BaseEntity{" +
                "id=" + id +
                ", createdAt=" + createdAt +
                ", updatedAt=" + updatedAt +
                ", deleted=" + deleted +
                ", createdBy=" + (createdBy != null ? createdBy.getId() : "null") +
                ", updatedBy=" + (updatedBy != null ? updatedBy.getId() : "null") +
                ", deletedAt=" + deletedAt +
                ", deletedBy=" + (deletedBy != null ? deletedBy.getId() : "null") +
                ", version=" + version +
                '}';
    }
}

Ich habe in HibernateUtil folgendes
Java:
package org.mjannek.database;

import javax.persistence.*;
import org.hibernate.*;
import org.hibernate.cfg.Configuration;
import org.hibernate.context.internal.ManagedSessionContext;
import org.reflections.*;

public class HibernateUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            Configuration configuration = new Configuration();
            configuration.configure();

            // Automatische Erkennung aller Entitäten im Paket
            Reflections reflections = new Reflections("org.mjannek.sport.buli.tables");
            for (Class<?> clazz : reflections.getTypesAnnotatedWith(Entity.class)) {
                configuration.addAnnotatedClass(clazz);
            }

            return configuration.buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public static Session openSessionWithFilters() {
        Session session = getSessionFactory().openSession();
        ManagedSessionContext.bind(session);

        // Standardmäßig den deletedFilter aktivieren
        session.enableFilter("deletedFilter").setParameter("isDeleted", false);

        return session;
    }

    public static void closeSession() {
        Session session = ManagedSessionContext.unbind(sessionFactory);
        if (session != null) {
            session.close();
        }
    }

    public static void shutdown() {
        getSessionFactory().close();
    }
}

In meiner Main-Klasse rufe ich folgendes auf:
Java:
package org.mjannek.database;

import org.hibernate.Session;
import org.hibernate.Transaction;

public class EntityFinder {
    public static void main(String[] args) {
        Session session = HibernateUtil.openSessionWithFilters();
        Transaction transaction = null;

        try {
            transaction = session.beginTransaction();


        }catch (Exception e){

        }
    }
}

Ich erhalte jedoch folgende Fehlermeldung:
Caused by: com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Incorrect datetime value: '0000-00-00 00:00:00' for column 'createdat' at row 1
Was kann ich da besser machen?
 

Marinek

Bekanntes Mitglied
Ich habe mir das als Basis für jede Entität erstellt, da ich möchte, dass jede Tabelle eine Spalte ID hat. Könnte man in der Klasse noch etwas anderes hinzufügen? Außer Spalten createdAt oder UpdatedAt


Klar geht das.. Warum sollte das nicht gehen?

Zu dem anderen Problem: Warum auch immer scheint dein Updatedatum Null zu sein. Daraus macht er 0000-- ... Das geht aber in mysql nicht.

Ich sehe leider nicht, wo du deine Entität erstellst, und wie du sie persistierst.

Du solltest mal debuggen, ob die Methoden @PrePersist und PreUpdate korrekt ausgeführt werden.

Eventuell ruft eine andere Stelle diese auf und ersetzt die Werte.

Scheint aber soweit alles korrekt zu sein.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
F mysql_num_rows() - Äquivalent Datenbankprogrammierung 5

Ähnliche Java Themen

Neue Themen


Oben