Skip to content
Snippets Groups Projects
Commit df690d90 authored by Martin Lowe's avatar Martin Lowe :flag_ca:
Browse files

Prototype for RDBMS projection functionality

Contains 2 options, one finished, the other half finished for
review/eval by Mika.
parent f9791ee6
No related branches found
No related tags found
1 merge request!19Prototype for RDBMS projection functionality
Pipeline #18337 passed
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipsefoundation</groupId>
<artifactId>quarkus-persistence-parent</artifactId>
<version>0.4-SNAPSHOT</version>
</parent>
<artifactId>quarkus-persistence</artifactId>
<name>Persistence - Runtime</name>
<dependencies>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipsefoundation</groupId>
<artifactId>quarkus-persistence-parent</artifactId>
<version>0.4-SNAPSHOT</version>
</parent>
<properties>
<hibernate.version>5.5.6.Final</hibernate.version>
</properties>
<artifactId>quarkus-persistence</artifactId>
<name>Persistence - Runtime</name>
<dependencies>
<dependency>
<groupId>org.eclipsefoundation</groupId>
<artifactId>quarkus-core</artifactId>
......@@ -62,37 +65,42 @@
<version>1.4.200</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bootstrap-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>extension-descriptor</goal>
</goals>
<configuration>
<deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}</deployment>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bootstrap-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>extension-descriptor</goal>
</goals>
<configuration>
<deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}</deployment>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</path>
<path>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>${hibernate.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
......@@ -9,9 +9,14 @@ package org.eclipsefoundation.persistence.dao;
import java.util.List;
import javax.enterprise.event.Observes;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipsefoundation.core.exception.MaintenanceException;
import org.eclipsefoundation.persistence.dto.BareNode;
import org.eclipsefoundation.persistence.model.RDBMSProjectionCriteria;
import org.eclipsefoundation.persistence.model.RDBMSQuery;
import io.quarkus.runtime.StartupEvent;
......@@ -70,6 +75,40 @@ public interface PersistenceDao extends HealthCheck {
*/
<T extends BareNode> T getReference(Object id, Class<T> type);
boolean isMaintenanceMode();
EntityManager getEntityManager();
/**
* Retrieves a projection of entities using the current entity manager to query the data.
*
* @param <T> the type of data that is being retrieved
* @param pc the projection criteria for the query
* @return list of results for the current
*/
default <T> List<T> retrieveProjection(RDBMSProjectionCriteria<T> pc) {
if (isMaintenanceMode()) {
throw new MaintenanceException();
}
EntityManager em = getEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<T> cq = cb.createQuery(pc.getTarget());
// --START this was previous sol'n
// set up the clauses if present
cq.select(pc.getSelect(cq, cb));
if (pc.hasWhereClause()) {
cq.where(pc.getWhere(cq, cb));
}
if (pc.hasGroupByClause()) {
cq.groupBy(pc.getGroupBy(cq, cb));
}
// --END, would use the created cq object in query below if active
// run the projection query and return
return em.createQuery(pc.getCriteriaQuery(cb)).getResultList();
}
default void startup(@Observes StartupEvent event) {
// intentionally empty
}
......
......@@ -47,7 +47,7 @@ public abstract class BaseHibernateDao implements PersistenceDao {
@Override
public <T extends BareNode> List<T> get(RDBMSQuery<T> q) {
if (maintenanceFlag) {
if (isMaintenanceMode()) {
throw new MaintenanceException();
}
// handle root request parameters (setting headers to track limit and max count)
......@@ -58,8 +58,7 @@ public abstract class BaseHibernateDao implements PersistenceDao {
LOGGER.debug("Querying DB using the following query: {}", q.getFilter().getSelectSql());
}
// build base query
TypedQuery<T> query = getEntityManager().createQuery(q.getFilter().getSelectSql(),
q.getDocType());
TypedQuery<T> query = getEntityManager().createQuery(q.getFilter().getSelectSql(), q.getDocType());
// add ordinal parameters
int ord = 1;
......@@ -80,7 +79,7 @@ public abstract class BaseHibernateDao implements PersistenceDao {
@Transactional
@Override
public <T extends BareNode> List<T> add(RDBMSQuery<T> q, List<T> documents) {
if (maintenanceFlag) {
if (isMaintenanceMode()) {
throw new MaintenanceException();
}
if (LOGGER.isDebugEnabled()) {
......@@ -113,7 +112,7 @@ public abstract class BaseHibernateDao implements PersistenceDao {
@Transactional
@Override
public <T extends BareNode> void delete(RDBMSQuery<T> q) {
if (maintenanceFlag) {
if (isMaintenanceMode()) {
throw new MaintenanceException();
}
......@@ -132,7 +131,7 @@ public abstract class BaseHibernateDao implements PersistenceDao {
@Transactional
@Override
public Long count(RDBMSQuery<?> q) {
if (maintenanceFlag) {
if (isMaintenanceMode()) {
throw new MaintenanceException();
}
if (LOGGER.isDebugEnabled()) {
......@@ -154,16 +153,15 @@ public abstract class BaseHibernateDao implements PersistenceDao {
@Override
public <T extends BareNode> T getReference(Object id, Class<T> type) {
if (maintenanceFlag) {
if (isMaintenanceMode()) {
throw new MaintenanceException();
}
return getEntityManager().getReference(type, id);
}
/**
* Handles operations that should happen on a "root" or main DB request for a
* fulfilled request. This is done to ensure that values such as DB max are
* abided.
* Handles operations that should happen on a "root" or main DB request for a fulfilled request. This is done to
* ensure that values such as DB max are abided.
*/
private void handleRoot(RDBMSQuery<?> q) {
// check if count has been performed, if not do so and set it to the response
......@@ -192,7 +190,7 @@ public abstract class BaseHibernateDao implements PersistenceDao {
@Override
public HealthCheckResponse call() {
HealthCheckResponseBuilder b = HealthCheckResponse.named("DB readiness");
if (maintenanceFlag) {
if (isMaintenanceMode()) {
return b.down().withData("error", "Maintenance flag is set").build();
}
return b.up().build();
......@@ -205,7 +203,13 @@ public abstract class BaseHibernateDao implements PersistenceDao {
* @param persistenceUnit the persistence unit targeted for the transaction
* @return entity manager object linked to current transaction
*/
protected EntityManager getEntityManager() {
@Override
public EntityManager getEntityManager() {
return inner;
}
@Override
public boolean isMaintenanceMode() {
return maintenanceFlag;
}
}
......@@ -2,6 +2,8 @@ package org.eclipsefoundation.persistence.dao.impl;
import java.util.List;
import javax.persistence.EntityManager;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipsefoundation.persistence.dao.PersistenceDao;
import org.eclipsefoundation.persistence.dto.BareNode;
......@@ -47,4 +49,16 @@ public class PlaceholderPersistenceDao implements PersistenceDao {
throw new IllegalStateException("Placeholder DAO should not be used in running instances");
}
@Override
public boolean isMaintenanceMode() {
// TODO Auto-generated method stub
return false;
}
@Override
public EntityManager getEntityManager() {
// TODO Auto-generated method stub
return null;
}
}
package org.eclipsefoundation.persistence.model;
import java.util.List;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Selection;
/**
*
* Simple wrapper to RDBMS projection queries to encapsulate suppliers. Suppliers are used as the criteria objects
* created from the current session is used as the base for the calls.
*
* @author Martin Lowe
*
*/
public final class RDBMSProjectionCriteria<T> {
private Function<CriteriaBuilder, CriteriaQuery<T>> querySupplier;
private BiFunction<CriteriaQuery<T>, CriteriaBuilder, List<Expression<?>>> groupBySupplier;
private BiFunction<CriteriaQuery<T>, CriteriaBuilder, Selection<T>> selectSupplier;
private BiFunction<CriteriaQuery<T>, CriteriaBuilder, Expression<Boolean>> whereSupplier;
private Class<T> type;
private RDBMSProjectionCriteria(Function<CriteriaBuilder, CriteriaQuery<T>> querySupplier,
BiFunction<CriteriaQuery<T>, CriteriaBuilder, List<Expression<?>>> groupBySupplier,
BiFunction<CriteriaQuery<T>, CriteriaBuilder, Selection<T>> selectSupplier,
BiFunction<CriteriaQuery<T>, CriteriaBuilder, Expression<Boolean>> whereSupplier, Class<T> type) {
this.querySupplier = querySupplier;
this.groupBySupplier = groupBySupplier;
this.selectSupplier = selectSupplier;
this.whereSupplier = whereSupplier;
this.type = type;
}
public CriteriaQuery<T> getCriteriaQuery(CriteriaBuilder cb) {
return querySupplier.apply(cb);
}
public List<Expression<?>> getGroupBy(CriteriaQuery<T> cq, CriteriaBuilder cb) {
return groupBySupplier.apply(cq, cb);
}
public Selection<T> getSelect(CriteriaQuery<T> cq, CriteriaBuilder cb) {
return selectSupplier.apply(cq, cb);
}
public Expression<Boolean> getWhere(CriteriaQuery<T> cq, CriteriaBuilder cb) {
return whereSupplier.apply(cq, cb);
}
public boolean hasGroupByClause() {
return this.groupBySupplier != null;
}
public boolean hasWhereClause() {
return this.whereSupplier != null;
}
public Class<T> getTarget() {
return type;
}
public static class RDBMSProjectionCriteriaBuilder<T> {
private Function<CriteriaBuilder, CriteriaQuery<T>> querySupplier;
private BiFunction<CriteriaQuery<T>, CriteriaBuilder, List<Expression<?>>> groupBySupplier;
private BiFunction<CriteriaQuery<T>, CriteriaBuilder, Selection<T>> selectSupplier;
private BiFunction<CriteriaQuery<T>, CriteriaBuilder, Expression<Boolean>> whereSupplier;
private Class<T> type;
public RDBMSProjectionCriteriaBuilder<T> setQuerySupplier(
Function<CriteriaBuilder, CriteriaQuery<T>> querySupplier) {
this.querySupplier = querySupplier;
return this;
}
public RDBMSProjectionCriteriaBuilder<T> setGroupBySupplier(
BiFunction<CriteriaQuery<T>, CriteriaBuilder, List<Expression<?>>> groupBySupplier) {
this.groupBySupplier = groupBySupplier;
return this;
}
public RDBMSProjectionCriteriaBuilder<T> setSelectSupplier(
BiFunction<CriteriaQuery<T>, CriteriaBuilder, Selection<T>> selectSupplier) {
this.selectSupplier = selectSupplier;
return this;
}
public RDBMSProjectionCriteriaBuilder<T> setWhereSupplier(
BiFunction<CriteriaQuery<T>, CriteriaBuilder, Expression<Boolean>> whereSupplier) {
this.whereSupplier = whereSupplier;
return this;
}
public RDBMSProjectionCriteriaBuilder<T> setType(Class<T> type) {
this.type = type;
return this;
}
public RDBMSProjectionCriteria<T> build() {
return new RDBMSProjectionCriteria<>(querySupplier, groupBySupplier, Objects.requireNonNull(selectSupplier),
whereSupplier, Objects.requireNonNull(type));
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment