-
Notifications
You must be signed in to change notification settings - Fork 0
Database DE
Aurora kann euch sehr viel Arbeit abnehmen, wenn es darum geht, mit Datenbanken zu arbeiten.
Inhaltsverzeichnis
Unterstützt | Datenbank-Implementation | StatementBuilder-Klasse | |
---|---|---|---|
MySQL | ✓ | MySQLDatabase | MySQLStatementBuilder |
import net.centurylab.aurora.database.implementations.MySQLDatabase;
import net.centurylab.aurora.database.statementbuilder.MySQLStatementBuilder;
public class DatabaseExample
{
public void selectExample()
{
MySQLDatabase database = new MySQLDatabase("localhost", "database", "user", "password");
MySQLStatementBuilder mySQLStatementBuilder = MySQLStatementBuilder.Select();
mySQLStatementBuilder.addField("username");
mySQLStatementBuilder.addTable("users");
database.execute(mySQLStatementBuilder).subscribe(parsedResultSet ->
{
String username = parsedResultSet.getString("username");
// do something with username
});
}
}
In diesem Beispiel wird nur das Feld "username" von der Tabelle "users" abgefragt. Hierbei bekommt ihr alle Einträge, da keine Bedingungen hinzugefügt worden sind.
import net.centurylab.aurora.database.Condition;
import net.centurylab.aurora.database.implementations.MySQLDatabase;
import net.centurylab.aurora.database.statementbuilder.MySQLStatementBuilder;
public class DatabaseExample
{
public void selectExample()
{
MySQLDatabase database = new MySQLDatabase("localhost", "database", "user", "password");
MySQLStatementBuilder mySQLStatementBuilder = MySQLStatementBuilder.Select();
mySQLStatementBuilder.addField("username");
mySQLStatementBuilder.addTable("users");
mySQLStatementBuilder.addCondition(new Condition("username", "=", "exampleUsername"));
database.execute(mySQLStatementBuilder).subscribe(parsedResultSet ->
{
String username = parsedResultSet.getString("username");
// do something with username
});
}
}
In diesem Beispiel gibt es nur eine kleine Änderung:
mySQLStatementBuilder.addCondition(new Condition("username", "=", "exampleUsername"));
Damit sagen wir dem StatementBuilder, dass wir nur an Daten interessiert sind, wo das Feld "username" den Inhalt "exampleUsername" hat. Ihr könnt hierbei so viele Bedingungen hinzufügen wie ihr wollt. Beachtet dabei, dass ihr für die zweite bis x-te Bedingung den Konstruktor nehmt:
public Condition(String clause, String field, String operator, Object value)
Der Parameter "clause" gibt dem StatementBuilder bescheid, wie er die Bedingung anhängen soll. Gültige Argumente sind "AND" und "OR".
import net.centurylab.aurora.database.OrderField;
import net.centurylab.aurora.database.OrderType;
import net.centurylab.aurora.database.implementations.MySQLDatabase;
import net.centurylab.aurora.database.statementbuilder.MySQLStatementBuilder;
public class DatabaseExample
{
public void selectExample()
{
MySQLDatabase database = new MySQLDatabase("localhost", "database", "user", "password");
MySQLStatementBuilder mySQLStatementBuilder = MySQLStatementBuilder.Select();
mySQLStatementBuilder.addField("*");
mySQLStatementBuilder.addTable("users");
mySQLStatementBuilder.addOrderField(new OrderField("id", OrderType.ASCENDING));
database.execute(mySQLStatementBuilder).subscribe(parsedResultSet ->
{
String username = parsedResultSet.getString("username");
// do something with username
});
}
}
In diesem Beispiel gibt es zwei Änderungen:
mySQLStatementBuilder.addField("*");
Hiermit sagen wir dem StatementBuilder, dass wir gerne alle Felder selektieren möchten (nicht nur ein einzelnes(in den voherigen Beispielen war es das Feld "username")).
mySQLStatementBuilder.addOrderField(new OrderField("id", OrderType.ASCENDING));
Damit weiß der StatementBuilder, dass wir die Daten gerne nach dem Feld "id" aufsteigend sortiert hätten. Eine absteigende Sortierung bekommt ihr mit OrderType.DESCENDING. Ihr könnt so viele Felder zum Sortieren hinzufügen wie ihr möchtet (wenn es die Implementation erlaubt).
Unterstützt mehrere Felder zum Sortieren | |
---|---|
MySQL | ✓ |
Stellt euch vor unsere "users" Tabelle ist wie folgt aufgebaut:
id | username |
---|---|
1 | user1 |
2 | user2 |
3 | user3 |
4 | user4 |
Mit Hilfe von "limit" können wir uns eine bestimmte Anzahl an Datensätzen zurückgeben lassen.
mySQLStatementBuilder.limit(2, 0);
Würde uns user1 und user2 zurückgeben. Denn wir wollen nur 2 (erster Parameter) Einträge ab Zeile 0 (zweiter Parameter).
mySQLStatementBuilder.limit(2, 2);
Würde uns user3 und user4 zurückgeben. Denn wir wollen nur 2 (erster Parameter) Einträge ab Zeile 2 (zweiter Parameter).
Wenn ihr Bedingungen oder Felder zum Sortieren löschen wollt, gibt es jeweils zwei Methoden, mit welchen ihr das erreichen könnt.
Die Daten werden entsprechend eurer Aufrufe nach in eine ArrayList hinzugefügt.
Bedingungen | Sortierfelder | |
---|---|---|
mit Index löschen | deleteCondition(int) | removeOrderField(int) |
mit Objekt löschen | deleteCondition(Condition) | removeOrderField(OrderField) |
Nun werdet ihr die wahre Stärke vom StatementBuilder sehen. Noch nie war es einfacher Daten in eine Tabelle einzufügen. Nehmen wir an wir haben immernoch die Tabelle von Abfrage von Daten (mit Sortierung). Beim Einfügen ist es wichtig, dass ihr alle Felder angebt die nicht "null" sein dürfen. Felder mit der Eigenschaft "auto increment" sind dabei außen vor, da kümmert sich dann das Datenbanksystem für uns.
Die generierte ID könnt ihr mit
mySQLStatementBuilder.setReturnGeneratedKeys(true);
bekommen.
import net.centurylab.aurora.database.implementations.MySQLDatabase;
import net.centurylab.aurora.database.statementbuilder.MySQLStatementBuilder;
import java.util.HashMap;
import java.util.Map;
public class DatabaseExample
{
public void insertExample()
{
MySQLDatabase database = new MySQLDatabase("localhost", "database", "user", "password");
Map<String, Object> values = new HashMap<>();
values.put("username", "GitHub-Wiki");
MySQLStatementBuilder mySQLStatementBuilder = MySQLStatementBuilder.Insert(values);
mySQLStatementBuilder.addTable("users");
database.execute(mySQLStatementBuilder).subscribe(parsedResultSet ->
{
int insertedRows = parsedResultSet.getUpdateCount();
});
}
}
Hier haben wir gleich eine Hand voll Änderungen. Gehen wir das im Einzelnen durch.
Map<String, Object> values = new HashMap<>();
values.put("username", "GitHub-Wiki");
Wir erstellen uns hier eine neue HashMap, welche als Schlüssel den Spaltennamen hat und als Wert den Wert, der später in der Datenbank eingetragen wird.
MySQLStatementBuilder mySQLStatementBuilder = MySQLStatementBuilder.Insert(values);
Natürlich müssen wir dem StatementBuilder noch sagen das wir Daten einfügen möchten.
mySQLStatementBuilder.addTable("users");
Wir müssen noch eine Tabelle angeben, wo die Daten eingefügt werden sollen.
int insertedRows = parsedResultSet.getUpdateCount();
Gibt uns die Anzahl der eingefügten Daten zurück.
Natürlich darf das aktualisieren von Daten nicht fehlen.
import net.centurylab.aurora.database.Condition;
import net.centurylab.aurora.database.implementations.MySQLDatabase;
import net.centurylab.aurora.database.statementbuilder.MySQLStatementBuilder;
import java.util.HashMap;
import java.util.Map;
public class DatabaseExample
{
public void updateExample()
{
MySQLDatabase database = new MySQLDatabase("localhost", "database", "user", "password");
Map<String, Object> values = new HashMap<>();
values.put("username", "GitHub-Wiki");
MySQLStatementBuilder mySQLStatementBuilder = MySQLStatementBuilder.Update(values);
mySQLStatementBuilder.addTable("users");
mySQLStatementBuilder.addCondition(new Condition("id", "=", 1));
database.execute(mySQLStatementBuilder).subscribe(parsedResultSet ->
{
int updatedRows = parsedResultSet.getUpdateCount();
});
}
}
Genau wie beim Einfügen von Daten geben wir der Methode unsere HashMap mit, mit den Daten, mit denen sie aktualisiert werden sollen. Dazu können wir noch weitere Bedingungen hinzufügen, um dem Datenbanksystem zu sagen, welche Zeilen genau aktualisiert werden sollen. Hier im Beispiel muss die ID der Zeile "1" sein. Natürlich könnt ihr auch allgemeinere Bedingungen verwenden und seit nicht daran gebunden, es nur auf eine Spalte zu beziehen.
int updatedRows = parsedResultSet.getUpdateCount();
Gibt uns die Anzahl der aktualisierten Zeilen zurück.
Mit Hilfe von Aurora könnt ihr ganz bequem Daten löschen.
import net.centurylab.aurora.database.Condition;
import net.centurylab.aurora.database.implementations.MySQLDatabase;
import net.centurylab.aurora.database.statementbuilder.MySQLStatementBuilder;
public class DatabaseExample
{
public void deleteExample()
{
MySQLDatabase database = new MySQLDatabase("localhost", "database", "user", "password");
MySQLStatementBuilder mySQLStatementBuilder = MySQLStatementBuilder.Delete();
mySQLStatementBuilder.addTable("users");
mySQLStatementBuilder.addCondition(new Condition("id", "=", 1));
database.execute(mySQLStatementBuilder).subscribe(parsedResultSet ->
{
int deletedRows = parsedResultSet.getUpdateCount();
});
}
}
MySQLStatementBuilder mySQLStatementBuilder = MySQLStatementBuilder.Delete();
mySQLStatementBuilder.addTable("users");
mySQLStatementBuilder.addCondition(new Condition("id", "=", 1));
Wir müssen nur angeben, von welcher Tabelle mit welchen Bedingungen wir die Daten löschen wollen.
int deletedRows = parsedResultSet.getUpdateCount();
Gibt uns zurück, wie viele Zeilen gelöscht worden sind.
Mit dem ParsedResultSet zu arbeiten ist sehr einfach. Die Verbindung zum normalen ResultSet wird schon getrennt, bevor ihr das ParsedResultSet überhaupt bekommt. Damit hat der Connection-Pool (in dem Fall HikariCP) die Verbindung zur Datenbank schnellstmöglich wieder und hat so Resourcen für die nächsten Abfragen, während ihr so lange wie ihr wollt mit dem ParsedResultSet arbeiten könnt.
Es gibt nur drei Sachen zu beachten, beim Arbeiten mit dem ParsedResultSet.
- Wenn ihr mit "SELECT" Daten abfragt, ist getUpdateCount() -1;
- Wenn ihr mit "INSERT" Daten einfügt und setReturnGeneratedKeys(true) benutzt, bekommt ihr mit parsedResultSet.getGeneratedKeys() die generierte ID(s) zurück
- Wenn ihr mit "INSERT", "UPDATE" oder "DELETE" Daten manipuliert, ist getUpdateCount() immer die Anzahl der betroffenen Datensätze.
Durch das Database-Interface wird vorgeschrieben, dass die execute-Methode ein io.reactivex.Observable zurückgeben muss. Dadurch brauch man seitens der Implementation nicht auf asynchronität achten, da man das Observable einfach auf einen Scheduler einschreiben kann. Wer sich etwas mehr mit den Schedulern auseinandersetzen will, findet im Packet "io.reactivex.schedulers" die Schedulers-Klasse, wo man auch einen eigenen erstellen kann anhand eines java.util.concurrent.Executor. Doch nun zurück zur asynchronen Datenbankabfrage.
import io.reactivex.schedulers.Schedulers;
import net.centurylab.aurora.database.Condition;
import net.centurylab.aurora.database.implementations.MySQLDatabase;
import net.centurylab.aurora.database.statementbuilder.MySQLStatementBuilder;
public class DatabaseExample
{
public void deleteExample()
{
MySQLDatabase database = new MySQLDatabase("localhost", "database", "user", "password");
MySQLStatementBuilder mySQLStatementBuilder = MySQLStatementBuilder.Delete();
mySQLStatementBuilder.addTable("users");
mySQLStatementBuilder.addCondition(new Condition("id", "=", 1));
database.execute(mySQLStatementBuilder).subscribeOn(Schedulers.computation()).subscribe(parsedResultSet ->
{
int deletedRows = parsedResultSet.getUpdateCount();
});
}
}
Hier fällt uns eine Änderung auf:
database.execute(mySQLStatementBuilder).subscribeOn(Schedulers.computation()).subscribe(parsedResultSet ->
Mit Hilfe von "subscribeOn(Schedulers.computation())" lassen wir unseren Beobachter auf einem anderem Thread laufen. Folgende Tabelle hilft euch herauszufinden, ob eine Abfrage oder der Beobachter asynchron ausgeführt wird oder nicht.
Scheduler | Asynchron |
---|---|
Schedulers.computation() | ✓ |
Schedulers.io() | ✓ |
Schedulers.newThread() | ✓ |
Schedulers.single() | X |
Schedulers.trampoline() | X |