All Downloads are FREE. Search and download functionalities are using the official Maven repository.

info.unterrainer.commons.httpserver.daos.JpqlCoreDao Maven / Gradle / Ivy

There is a newer version: 0.3.14
Show newest version
package info.unterrainer.commons.httpserver.daos;

import java.lang.reflect.InvocationTargetException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.LockModeType;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import javax.persistence.TypedQuery;

import org.mapstruct.ap.internal.util.Strings;

import info.unterrainer.commons.httpserver.exceptions.ForbiddenException;
import info.unterrainer.commons.httpserver.exceptions.InternalServerErrorException;
import info.unterrainer.commons.httpserver.jpas.BasicPermissionJpa;
import info.unterrainer.commons.httpserver.jsons.ListJson;
import info.unterrainer.commons.jreutils.DateUtils;
import info.unterrainer.commons.rdbutils.entities.BasicJpa;
import info.unterrainer.commons.rdbutils.enums.AsyncState;
import io.javalin.http.Context;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class JpqlCoreDao

implements CoreDao { protected final Class

type; @Getter protected JpqlTransactionManager transactionManager; @Getter protected TenantData tenantData; public JpqlCoreDao(final EntityManagerFactory emf, final Class

type) { super(); this.type = type; transactionManager = new JpqlTransactionManager(emf, null); } public JpqlCoreDao(final Function entityManagerFactorySupplier, final Class

type) { super(); this.type = type; transactionManager = new JpqlTransactionManager(null, entityManagerFactorySupplier); } @Override public P create(final EntityManager em, final P entity, final Set tenantIds) { LocalDateTime time = DateUtils.nowUtc(); entity.setCreatedOn(time); entity.setEditedOn(time); em.persist(entity); if (hasTenantData()) try { for (Long tenantId : tenantIds) { BasicPermissionJpa tenantJpa = tenantData.getPermissionJpaType().getConstructor().newInstance(); tenantData.getReferenceSetMethod().invoke(tenantJpa, entity.getId()); tenantData.getTenantIdSetMethod().invoke(tenantJpa, tenantId); tenantJpa.setCreatedOn(time); tenantJpa.setEditedOn(time); em.persist(tenantJpa); } } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { throw new InternalServerErrorException(String.format("Error creating permission-entry in [%s]", tenantData.getPermissionJpaType().getSimpleName())); } return entity; } @Override public void delete(final EntityManager em, final Long id, final Set tenantIds) { if (!isAllowed(em, id, tenantIds)) return; em.createQuery(String.format("DELETE FROM %s AS o WHERE o.id = :id", type.getSimpleName())) .setParameter("id", id) .executeUpdate(); } @Override public P getById(final EntityManager em, final Long id, final Set tenantIds) { try { return getQuery(em, "o", null, "o.id = :id", Map.of("id", id), type, null, false, null, tenantIds) .getSingleResult(); } catch (NoResultException e) { return null; } } @Override public ListJson

getList(final EntityManager em, final Long offset, final Long size, final String selectClause, final String joinClause, final String whereClause, final ParamMap params, final String orderByClause, final Set tenantIds) { ListJson

r = new ListJson<>(); r.setEntries(getList(em, getQuery(em, selectClause, joinClause, whereClause, params == null ? null : params.getParameters(), type, orderByClause, false, null, tenantIds), offset, size)); r.setCount((Long) getCountQuery(em, selectClause, joinClause, whereClause, params == null ? null : params.getParameters(), null, tenantIds).getSingleResult()); return r; } @Override public P update(final EntityManager em, final P entity, final Set tenantIds) { if (!isAllowed(em, entity.getId(), tenantIds)) throw new ForbiddenException(); LocalDateTime time = DateUtils.nowUtc(); entity.setEditedOn(time); return em.merge(entity); } TypedQuery getQuery(final EntityManager em, final String selectClause, String joinClause, String whereClause, Map params, final Class type, final String orderBy, final boolean lockPessimistic, final Set asyncStates, final Set tenantIds) { String query = "SELECT "; if (selectClause == null || selectClause.isBlank()) query += "o"; else query += selectClause; query += " FROM %s AS o"; joinClause = addTenantJoin(joinClause); if (joinClause != null && !joinClause.isBlank()) query += " " + joinClause; whereClause = addTenantWhere(whereClause, tenantIds); query += buildWhereClause(whereClause, asyncStates); if (orderBy == null) query += " ORDER BY o.id ASC"; else if (!orderBy.isBlank()) query += " ORDER BY " + orderBy; log.debug("Query is: [{}]", query); query = String.format(query, this.type.getSimpleName()); @SuppressWarnings("unchecked") Class t = (Class) this.type; if (type != null) t = type; TypedQuery q = em.createQuery(query, t); if (lockPessimistic) q.setLockMode(LockModeType.PESSIMISTIC_WRITE); log.debug(" with lockmode: [{}]", q.getLockMode()); if (asyncStates != null) log.debug(" with asynchronous_state: [{}]", Strings.join(asyncStates.stream().map(AsyncState::toString).collect(Collectors.toList()), ", ")); addAsyncStatesParamsToQuery(asyncStates, q); params = addTenantParams(params, tenantIds); if (params != null) { log.debug(" with parameters: [{}]", Strings.join(params.entrySet() .stream() .map(e -> e.getKey() + ": " + e.getValue().toString()) .collect(Collectors.toList()), ", ")); for (Entry e : params.entrySet()) q.setParameter(e.getKey(), e.getValue()); } return q; } Query getCountQuery(final EntityManager em, final String selectClause, String joinClause, String whereClause, Map params, final Set asyncStates, final Set tenantIds) { String query = "SELECT COUNT("; if (selectClause == null || selectClause.isBlank()) query += "o.id"; else query += selectClause; query += ") FROM %s AS o"; joinClause = addTenantJoin(joinClause); if (joinClause != null && !joinClause.isBlank()) query += " " + joinClause; whereClause = addTenantWhere(whereClause, tenantIds); query += buildWhereClause(whereClause, asyncStates); params = addTenantParams(params, tenantIds); Query q = em.createQuery(String.format(query, this.type.getSimpleName())); addAsyncStatesParamsToQuery(asyncStates, q); if (params != null) for (Entry e : params.entrySet()) q.setParameter(e.getKey(), e.getValue()); return q; } List getList(final EntityManager em, final TypedQuery query, final long offset, final long size) { int s = Integer.MAX_VALUE; if (size < s) s = (int) size; int o = Integer.MAX_VALUE; if (offset < o) o = (int) offset; query.setFirstResult(o); query.setMaxResults(s); return query.getResultList(); } private boolean isAllowed(final EntityManager em, final Long id, final Set tenantIds) { if (!hasTenantData()) return true; if (tenantIds == null) return false; if (tenantIds.contains(null)) return true; TypedQuery query = getQuery(em, "o.id", null, "o.id = :id", Map.of("id", id), Long.class, null, false, null, tenantIds); query.setMaxResults(1); List list = query.getResultList(); return list != null && list.size() > 0; } private String addTenantJoin(final String joinClause) { if (!hasTenantData()) return joinClause; String r = joinClause; if (joinClause == null || joinClause.isBlank()) r = ""; r += String.format(" LEFT JOIN %s tenantTable on o.id = tenantTable.%s", tenantData.getPermissionJpaType().getSimpleName(), tenantData.getMainTableIdReferenceField()); return r; } private String addTenantWhere(final String whereClause, final Set tenantIds) { if (!hasTenantData()) return whereClause; String r = ""; if (whereClause != null && !whereClause.isBlank()) r = "( " + whereClause + " ) AND "; r += String.format("( tenantTable.%1$s IS NULL", tenantData.getTenantIdField()); if (tenantIds != null && !tenantIds.isEmpty()) r += String.format(" OR tenantTable.%1$s IN (:tenantIds)", tenantData.getTenantIdField()); r += " )"; return r; } private Map addTenantParams(final Map map, final Set tenantIds) { Map m; if (map == null) m = new HashMap<>(); else m = new HashMap<>(map); if (!hasTenantData() || tenantIds == null || tenantIds.isEmpty()) return m; m.put("tenantIds", tenantIds); return m; } private boolean hasTenantData() { return tenantData != null && tenantData.getPermissionJpaType() != null && tenantData.getMainTableIdReferenceField() != null && tenantData.getTenantIdField() != null; } private boolean isSet(final String str) { return str != null && !str.isBlank(); } private boolean isSet(final Set set) { return set != null && !set.isEmpty(); } private String buildWhereClause(final String whereClause, final Set asyncStates) { String r = ""; if (!isSet(whereClause) && !isSet(asyncStates)) return r; r = " WHERE "; if (isSet(whereClause) && !isSet(asyncStates)) r += whereClause; if (isSet(asyncStates)) { if (isSet(whereClause)) r += "( " + whereClause + " ) AND "; r += "( o.state IN :asynchronous_state )"; } return r; } private void addAsyncStatesParamsToQuery(final Set asyncStates, final Query query) { if (!isSet(asyncStates)) return; query.setParameter("asynchronous_state", asyncStates); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy