-
Julian Horner authoredJulian Horner authored
NoSQL-Datenbank für My-Aktion
Worum geht es in diesem Projekt?
Die Aufgabe dieses Projekts ist es die relationale H2-Datenbank des Projekts my-aktion durch die NoSQL-Datenbank MongoDB zu ersetzen, sowie dem anpassen von my-aktion an die neue Datenbank.
Zur Umsetzung wurde das Mapping-Framework Hibernate OGM genutzt. Hibernate OGM mappt die Entities der Anwendung nicht wie Hibernate ORM, an eine relationale Datenbank sondern an eine NoSQL-Datenbank. Im Falle des Projekt also an die MongoDB-Datenbank.
Hibernate OGM ist dazu in der Lage JPQL-Queries zu übersetzen in die Sprache der jeweilig angebundenen Datenbank. Der Programmierer muss also die Abfragesprache der genutzten Datenbank nicht zwangsläufig kennen. Auch die von der Anwendung genutzten JPA-Annotationen wie zum Beispiel NotNull oder ManyToOne werden unterstützt, also müssen auch hier keine Anpassungen vorgenommen werden.
Aufgetretene Probleme
Aggregatfunktionen in Hibernate OGM
Da Hibernate OGM ein laufender Prozess können bislang nur manche Sprachkonstrukte von JPQL in andere Abfragesprachen übersetzt werden. Was genau übersetzt wird unterscheidet sich je nach genutzter Datenbank. Die Version für MongoDB-Datenbanken unterstützt die folgenden Teile von JPQL:
- simple comparisons using "<", "⇐", "=", ">=" and ">"
-
IS NULL
andIS NOT NULL
- the boolean operators
AND
,OR
,NOT
-
LIKE
,IN
andBETWEEN
ORDER BY
Im Projekt my-aktion wird an einer Stelle die SQL-Aggregatfunktion SUM genutzt, diese wird theoretisch nicht unterstützt konnte aber mit einem "workaround" dennoch genutzt werden. Die restlichen Queries konnten Problemlos weiter genutzt werden ohne spezielle Anpassungen vornehmen zu müssen.
Der unten dargestellte Code zeigt die Methode in welcher die Abfrage mit der Summenfunktion aufgerufen wird. Aus einem bisher unerfindlichen Grund funktioniert die Summenfunktion so obwohl diese eigentlich nicht unterstützt sein sollte. Der einzige Unterschied zwischen diesem und den anderen Methoden in der Klasse ist der dass anstatt über JPA-API direkt die Hibernate-Native-API genutzt wird.
Da im Code nur auf das Session-Interface zugegriffen wird und nicht direkt auf die OgmSession, sollte die Methode auch mit einer Hibernate-ORM-Lösung lauffähig sein, müsste also nicht angepasst werden.
@RolesAllowed("Organizer")
@Stateless
public class CampaignServiceBean implements CampaignService {
// ----------------------------------------------------------------------------------------------
...
private Double getAmountDonatedSoFar(Campaign campaign) {
Session session = entityManager.unwrap(Session.class);
Double result = session.createNamedQuery(Campaign.getAmountDonatedSoFar, Double.class)
.setParameter("campaign", campaign).uniqueResult();
if (result == null)
result = 0d;
return result;
}
...
// ----------------------------------------------------------------------------------------------
}
Organizer-Dokument
Da die Dokumente in einer MongoDB-Datenbank immer einen eindeutigen Identifier im Feld _id haben müssen, wurde in die Organizer-Entity ein Feld Id eingefügt welches das email-Feld als Identifier ersetzt. Damit dennoch sichergestellt wird das eine bestimmte E-Mail nur einmal vorkommt in der Tabelle, wurde an das email-Feld die Annotation @Column(unique = true) angehängt (siehe untenstehender Code).
@Entity
public class Organizer extends DateEntity {
//----------------------------------------------------------------------------------------------
public static final String findByEmail = "Organizer.findByEmail";
//==============================================================================================
@GeneratedValue
@Id
private Long id;
@NotNull
@Size(min = 3, max = 20, message = "{organizer.firstName.size}")
private String firstName;
@NotNull
@Size(min = 3, max = 30, message = "{organizer.lastName.size}")
private String lastName;
@Pattern(regexp = ".+@.+", message = "{organizer.email.pattern}")
@Column(unique = true)
private String email;
@NotNull
private String password;
//----------------------------------------------------------------------------------------------
...
}
Wie startet man das Projekt?
Voraussetzungen
- Eine MongoDB-Datenbank-Instanz muss auf dem Rechner laufen (unter default port und localhost).
- Die Datenbank muss den Namen my-aktion haben.
- Es muss eine Sammlung existieren in welchen die Benutzer der Applikation gespeichert werden.
- Die Sammlung welche die Benutzer enthält muss den Namen Organizer tragen.