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

com.jwebmp.entityassist.querybuilder.builders.QueryBuilderBase Maven / Gradle / Ivy

There is a newer version: 0.68.0.1
Show newest version
package com.jwebmp.entityassist.querybuilder.builders;

import com.google.inject.Key;
import com.jwebmp.entityassist.BaseEntity;
import com.jwebmp.entityassist.injections.EntityAssistBinder;
import com.jwebmp.entityassist.querybuilder.QueryBuilder;
import com.jwebmp.entityassist.querybuilder.statements.InsertStatement;
import com.jwebmp.entityassist.services.EntityAssistIDMapping;
import com.jwebmp.guicedinjection.GuiceContext;
import com.jwebmp.guicedpersistence.db.DbStartup;
import com.jwebmp.guicedpersistence.services.ITransactionHandler;
import com.jwebmp.logger.LogFactory;
import com.oracle.jaxb21.PersistenceUnit;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.Transient;
import javax.persistence.metamodel.Attribute;
import javax.sql.DataSource;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import static com.jwebmp.entityassist.querybuilder.EntityAssistStrings.*;
import static com.jwebmp.guicedpersistence.scanners.PersistenceServiceLoadersBinder.*;

/**
 * Builds a Query Base
 *
 * @param 
 * 		This class type
 * @param 
 * 		The entity type
 * @param 
 * 		The entity ID type
 */
@SuppressWarnings({"WeakerAccess", "UnusedReturnValue", "unused"})
public abstract class QueryBuilderBase, E extends BaseEntity, I extends Serializable>
{
	/**
	 * This logger
	 */
	private static final Logger log = LogFactory.getLog("QueryBuilderBase");
	/**
	 * The maximum number of results
	 */
	private Integer maxResults;
	/**
	 * The minimum number of results
	 */
	private Integer firstResults;
	/**
	 * The given entity class
	 */
	private Class entityClass;
	/**
	 * A Query to execute to return any generated ID
	 */
	private String selectIdentityString = "SELECT @@IDENTITY";
	/**
	 * The actual entity event
	 */
	private E entity;
	/**
	 * Whether or not to run these queries as detached objects or within the entity managers scope
	 */
	@Transient
	private boolean runDetached;
	/**
	 * If the inserted ID should be request override
	 */
	private boolean requestId = true;

	/**
	 * Constructor QueryBuilderBase creates a new QueryBuilderBase instance.
	 */
	protected QueryBuilderBase()
	{
		entityClass = getEntityClass();
	}

	/**
	 * Returns the associated entity class for this builder
	 *
	 * @return class of type entity
	 */
	protected Class getEntityClass()
	{
		return entityClass;
	}

	/**
	 * Returns a mapped entity on this builder
	 *
	 * @return the actual entity
	 */
	public E getEntity()
	{
		return entity;
	}

	/**
	 * Sets the entity for this particular builder
	 *
	 * @param entity
	 * 		The entity
	 *
	 * @return J This object
	 */
	@SuppressWarnings("unchecked")
	@NotNull
	public J setEntity(E entity)
	{
		this.entity = entity;
		entityClass = (Class) entity.getClass();
		return (J) this;
	}

	/**
	 * Returns the current set first results
	 *
	 * @return where to start the first results
	 */
	public Integer getFirstResults()
	{
		return firstResults;
	}

	/**
	 * Sets the first restults to return
	 *
	 * @param firstResults
	 * 		the number of results to skip before loading
	 *
	 * @return This
	 */
	@SuppressWarnings("unchecked")
	@NotNull
	public J setFirstResults(Integer firstResults)
	{
		this.firstResults = firstResults;
		return (J) this;
	}

	/**
	 * Returns the current set maximum results
	 *
	 * @return int
	 */
	public Integer getMaxResults()
	{
		return maxResults;
	}

	/**
	 * Sets the maximum results to return
	 *
	 * @param maxResults
	 * 		the maximum number of results to return
	 *
	 * @return This
	 */
	@SuppressWarnings("unchecked")
	@NotNull
	public J setMaxResults(Integer maxResults)
	{
		this.maxResults = maxResults;
		return (J) this;
	}

	/**
	 * Persist and Flush
	 * 

* doesn't set run detached - executes flush after persist * * @return This */ @NotNull @SuppressWarnings({"unchecked", "Duplicates"}) public J persistNow(E entity) { boolean transactionAlreadyStarted = false; PersistenceUnit unit = GuiceContext.get(Key.get(PersistenceUnit.class, getEntityManagerAnnotation())); for (ITransactionHandler handler : GuiceContext.get(ITransactionHandlerReader)) { if (handler.transactionExists(getEntityManager(), unit)) { transactionAlreadyStarted = true; break; } } for (ITransactionHandler handler : GuiceContext.get(ITransactionHandlerReader)) { if (!transactionAlreadyStarted && handler.active(unit)) { handler.beginTransacation(false, getEntityManager(), unit); } } persist(entity); getEntityManager().flush(); for (ITransactionHandler handler : GuiceContext.get(ITransactionHandlerReader)) { if (!transactionAlreadyStarted && handler.active(unit)) { handler.commitTransacation(false, getEntityManager(), unit); } } return (J) this; } /** * Returns the annotation associated with the entity manager * * @return The annotations associated with this builder */ @SuppressWarnings("unchecked") public Class getEntityManagerAnnotation() { EntityManager em = getEntityManager(); return (Class) em.getProperties() .get("annotation"); } /** * Returns the assigned entity manager * * @return The entity manager to use for this run */ @NotNull @Transient protected abstract EntityManager getEntityManager(); /** * Persists this entity. Uses the get instance entity manager to operate. * * @return This */ @SuppressWarnings("unchecked") @NotNull public J persist(E entity) { try { if (onCreate(entity)) { boolean transactionAlreadyStarted = false; com.oracle.jaxb21.PersistenceUnit unit = GuiceContext.get(Key.get(PersistenceUnit.class, getEntityManagerAnnotation())); if (isRunDetached()) { String insertString = InsertStatement.buildInsertString(entity); log.fine(insertString); //if(false) if(DbStartup.getAvailableDataSources().contains(getEntityManagerAnnotation())) { DataSource ds = GuiceContext.get(DataSource.class, getEntityManagerAnnotation()); try(Connection c = ds.getConnection();Statement st = c.createStatement()) { st.executeUpdate(insertString); if (isIdGenerated() && isRequestId()) { iterateThroughResultSetForGeneratedIDs(c); } } } else { Query query = getEntityManager().createNativeQuery(insertString); query.executeUpdate(); if (isIdGenerated() && isRequestId()) { iterateThroughResultSetForGeneratedIDs(); } } } else { getEntityManager().persist(entity); } entity.setFake(false); } } catch (IllegalStateException ise) { log.log(Level.SEVERE, "This entity is not in a state to be persisted. Perhaps an update merge remove or refresh?", ise); } catch (Exception e) { log.log(Level.SEVERE, "Unable to persist, exception occured\n", e); throw new UnsupportedOperationException(e); } return (J) this; } /** * Performed on create/persist * * @param entity * The entity * * @return true if must still create */ protected boolean onCreate(E entity) { return true; } /** * If this entity should run in a detached and separate to the entity manager *

* If the library generates the sql and runs it through a native query. Use InsertStatement, SelectStatement, Delete and UpdateStatement to view the queries that will get run * * @return boolean */ public boolean isRunDetached() { return runDetached; } /** * If this entity should run in a detached and separate to the entity manager *

* If the library generates the sql and runs it through a native query. Use InsertStatement, SelectStatement, Delete and UpdateStatement to view the queries that will get run * * @param runDetached * if must do * * @return This */ @SuppressWarnings("unchecked") @NotNull public J setRunDetached(boolean runDetached) { this.runDetached = runDetached; return (J) this; } /** * If this ID is generated from the source and which form to use * Default is Generated * * @return Returns if the id column is a generated type */ protected abstract boolean isIdGenerated(); /** * Getter for property 'requestId'. * * @return Value for property 'requestId'. */ public boolean isRequestId() { return requestId; } /** * Method iterateThroughResultSetForGeneratedIDs ... */ private void iterateThroughResultSetForGeneratedIDs() { Query statmentSelectId = getEntityManager().createNativeQuery(selectIdentityString); Object o = statmentSelectId.getSingleResult(); processId(o); } /** * Method iterateThroughResultSetForGeneratedIDs ... */ private void iterateThroughResultSetForGeneratedIDs(Connection connection) { DataSource ds = GuiceContext.get(DataSource.class, getEntityManagerAnnotation()); try(Statement st = connection.createStatement()) { ResultSet rs = st.executeQuery(selectIdentityString); if(rs.next()) { Object o = rs.getObject(1); processId(o); } } catch (SQLException e) { log.log(Level.WARNING, "Unable to get generatedID", e); } } /** * Method processId ... * * @param o * of type Object */ @SuppressWarnings("unchecked") private void processId(Object o) { EntityAssistIDMapping mapping = EntityAssistBinder.lookup(o.getClass(), entity.getClassIDType()); entity.setId((I) mapping.toObject(o)); } /** * Setter for property 'requestId'. * * @param requestId * Value to set for property 'requestId'. */ public void setRequestId(boolean requestId) { this.requestId = requestId; } /** * Persist and Flush using the detached method (as a native query) * * @return This */ @NotNull @SuppressWarnings({"unchecked", "Duplicates"}) public J persistNow(E entity, boolean runDetached) { boolean transactionAlreadyStarted = false; PersistenceUnit unit = GuiceContext.get(Key.get(PersistenceUnit.class, getEntityManagerAnnotation())); for (ITransactionHandler handler : GuiceContext.get(ITransactionHandlerReader)) { if (handler.active(unit) && handler.transactionExists(getEntityManager(), unit)) { transactionAlreadyStarted = true; break; } } for (ITransactionHandler handler : GuiceContext.get(ITransactionHandlerReader)) { if (!transactionAlreadyStarted && handler.active(unit)) { handler.beginTransacation(false, getEntityManager(), unit); } } setRunDetached(runDetached); persist(entity); for (ITransactionHandler handler : GuiceContext.get(ITransactionHandlerReader)) { if (!transactionAlreadyStarted && handler.active(unit)) { handler.commitTransacation(false, getEntityManager(), unit); } } return (J) this; } /** * Merges this entity with the database copy. Uses getInstance(EntityManager.class) * * @return This */ @NotNull @SuppressWarnings("unchecked") public E update(E entity) { try { if (onUpdate(entity)) { if (isRunDetached()) { getEntityManager().merge(entity); } else { getEntityManager().merge(entity); } } } catch (IllegalStateException ise) { log.log(Level.SEVERE, "Cannot update this entity the state of this object is not ready : \n", ise); } catch (Exception e) { log.log(Level.SEVERE, "Cannot update this entity unknown exception the state of this object is not ready : \n", e); } return entity; } /** * Performed on update/persist * * @param entity * The entity * * @return true if must carry on updating */ protected boolean onUpdate(E entity) { return true; } /** * Performs the constraint validation and returns a list of all constraint errors. * * Great for form checking * * @return List of Strings */ @NotNull public List validateEntity(E entity) { List errors = new ArrayList<>(); ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator(); Set constraintViolations = validator.validate(entity); if (!constraintViolations.isEmpty()) { for (Object constraintViolation : constraintViolations) { ConstraintViolation contraints = (ConstraintViolation) constraintViolation; String error = contraints.getRootBeanClass() .getSimpleName() + STRING_DOT + contraints.getPropertyPath() + STRING_EMPTY + contraints.getMessage(); errors.add(error); } } return errors; } /** * Returns the given attribute for a field name by reflectively accesing the static class * * @param fieldName * * @return */ public Attribute getAttribute(String fieldName) { String clazz = getEntityClass().getCanonicalName() + "_"; try { Class c = Class.forName(clazz); Field f = c.getField(fieldName); return (Attribute) f.get(null); } catch (Exception e) { log.log(Level.SEVERE, "Unable to field field in class [" + clazz + "]-[" + fieldName + "]", e); } return null; } /** * Method getSelectIdentityString returns the selectIdentityString of this QueryBuilderBase object. * * @return the selectIdentityString (type String) of this QueryBuilderBase object. */ public String getSelectIdentityString() { return selectIdentityString; } /** * Method setSelectIdentityString sets the selectIdentityString of this QueryBuilderBase object. * * @param selectIdentityString * the selectIdentityString of this QueryBuilderBase object. */ public void setSelectIdentityString(String selectIdentityString) { this.selectIdentityString = selectIdentityString; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy