Package railo.runtime.orm.hibernate

Source Code of railo.runtime.orm.hibernate.HibernateORMSession

package railo.runtime.orm.hibernate;

import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

import org.hibernate.Criteria;
import org.hibernate.FlushMode;
import org.hibernate.NonUniqueResultException;
import org.hibernate.QueryException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.engine.query.HQLQueryPlan;
import org.hibernate.engine.query.ParameterMetadata;
import org.hibernate.engine.query.QueryPlanCache;
import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.type.Type;

import railo.commons.lang.types.RefBoolean;
import railo.loader.util.Util;
import railo.runtime.Component;
import railo.runtime.ComponentScope;
import railo.runtime.PageContext;
import railo.runtime.db.DataSource;
import railo.runtime.db.DatasourceConnection;
import railo.runtime.db.SQLItem;
import railo.runtime.exp.PageException;
import railo.runtime.orm.ORMEngine;
import railo.runtime.orm.ORMSession;
import railo.runtime.orm.ORMTransaction;
import railo.runtime.type.Array;
import railo.runtime.type.Collection.Key;
import railo.runtime.type.Struct;
import railo.runtime.type.scope.Argument;

public class HibernateORMSession implements ORMSession{

  private Session _session;
  private DatasourceConnection dc;
  private SessionFactoryData data;

  public HibernateORMSession(SessionFactoryData data, DatasourceConnection dc){
    this.data=data;
    this.dc=dc;
    resetSession(data.getFactory());
  }
 
  private Session session(){
    return _session;
  }

  public SessionFactoryData getSessionFactoryData(){
    return data;
  }
 
  private SessionFactory getSessionFactory(PageContext pc){
    // engine.getSessionFactory(pc);
    return _session.getSessionFactory();
  }
  SessionFactory getSessionFactory(){
    // engine.getSessionFactory(pc);
    return _session.getSessionFactory();
  }
 
  void resetSession(SessionFactory factory) {
    _session = factory.openSession(dc.getConnection());
    _session.setFlushMode(FlushMode.MANUAL);
  }

  @Override
  public ORMEngine getEngine() {
    return data.getEngine();
  }
 
  @Override
  public void flush(PageContext pc) throws PageException {
    try {
      session().flush();
    }
    catch(ConstraintViolationException cve){
      PageException pe = ExceptionUtil.createException(this,null,cve);
      if(!Util.isEmpty(cve.getConstraintName())) {
        ExceptionUtil.setAdditional(pe, CommonUtil.createKey("constraint name"), cve.getConstraintName());
      }
      throw pe;
    }
    catch(Throwable t) {
      throw CommonUtil.toPageException(t);
    }
   
  }

  @Override
  public void delete(PageContext pc, Object obj) throws PageException {
    if(CommonUtil.isArray(obj)){
      Transaction trans = session().getTransaction();
      if(trans.isActive()) trans.begin();
      else trans=null;
     
      try{
        Iterator it = CommonUtil.toArray(obj).valueIterator();
        while(it.hasNext()){
          _delete(pc,HibernateCaster.toComponent(it.next()));
        }
      }
      catch(Throwable t){
        if(trans!=null)trans.rollback();
        throw CommonUtil.toPageException(t);
      }
      if(trans!=null)trans.commit();
    }
    else _delete(pc,HibernateCaster.toComponent(obj));
  }
 
  public void _delete(PageContext pc, Component cfc) throws PageException {
    data.checkExistent(pc,cfc);
    //Session session = getSession(pc,cfc);
   
    try{
      session().delete(HibernateCaster.getEntityName(cfc), cfc);
    }
    catch(Throwable t){
      throw CommonUtil.toPageException(t);
    }
  }
 
 
 
  @Override
  public void save(PageContext pc, Object obj,boolean forceInsert) throws PageException {
    Component cfc = HibernateCaster.toComponent(obj);
    //Session session = getSession(pc, cfc);
    String name = HibernateCaster.getEntityName(cfc);
    try {
      if(forceInsert)
        session().save(name, cfc);
      else
          session().saveOrUpdate(name, cfc);
    }
    catch(Throwable t){
      throw ExceptionUtil.createException(this,null,t);
    }
  }
 
  @Override
  public void reload(PageContext pc,Object obj) throws PageException {
    Component cfc = HibernateCaster.toComponent(obj);
    data.checkExistent(pc,cfc);
    //Session session = getSession(pc,cfc);
    session().refresh(cfc);
  }
 

  @Override
  public Component create(PageContext pc, String entityName)throws PageException {
    return data.getEngine().create(pc,this, entityName,true);
  }
 
  @Override
  public void clear(PageContext pc) throws PageException {
    session().clear();
  }
 
  @Override
  public void evictQueries(PageContext pc) throws PageException {
    evictQueries(pc, null);
  }

  @Override
  public void evictQueries(PageContext pc,String cacheName) throws PageException {
    SessionFactory f = getSessionFactory(pc);
    if(Util.isEmpty(cacheName))f.evictQueries();
    else f.evictQueries(cacheName);
  }
 
  @Override
  public void evictEntity(PageContext pc, String entityName) throws PageException {
    evictEntity(pc, entityName, null);
  }

  @Override
  public void evictEntity(PageContext pc, String entityName, String id) throws PageException {
    SessionFactory f = getSessionFactory(pc);
   
    if(id==null) {
      f.evictEntity(entityName);
    }
    else {
      f.evictEntity(entityName,CommonUtil.toSerializable(id));
    }
  }
 
  @Override
  public void evictCollection(PageContext pc, String entityName, String collectionName) throws PageException {
    evictCollection(pc, entityName, collectionName, null);
  }

  @Override
  public void evictCollection(PageContext pc, String entityName, String collectionName, String id) throws PageException {
    SessionFactory f = getSessionFactory(pc);
    String role=entityName+"."+collectionName;
    if(id==null) {
      f.evictCollection(role);
    }
    else {
      f.evictCollection(role,CommonUtil.toSerializable(id));
    }
  }
 
  
 
 
 
 
 

  @Override
  public Object executeQuery(PageContext pc,String hql, Array params, boolean unique,Struct queryOptions) throws PageException {
    return _executeQuery(pc, hql, params, unique, queryOptions);
  }

  @Override
  public Object executeQuery(PageContext pc,String hql, Struct params, boolean unique,Struct queryOptions) throws PageException {
    return _executeQuery(pc, hql, params, unique, queryOptions);
  }
 
  public Object _executeQuery(PageContext pc,String hql, Object params, boolean unique,Struct queryOptions) throws PageException {
    try{
      return __executeQuery(pc, hql, params, unique, queryOptions);
    }
    catch(QueryException qe) {
      // argument scope is array and struct at the same time, by default it is handled as struct, if this fails try it as array
      if(params instanceof Argument) {
        try{
          return __executeQuery(pc, hql, CommonUtil.toArray((Argument)params), unique, queryOptions);
        }
        catch(Throwable t){t.printStackTrace();}
      }
      throw qe;
    }
   
   
  }
 
  private Object __executeQuery(PageContext pc,String hql, Object params, boolean unique,Struct options) throws PageException {
    //Session session = getSession(pc,null);
    hql=hql.trim();
    org.hibernate.Query query = session().createQuery(hql);
    // options
    if(options!=null){
      // maxresults
      Object obj=options.get("maxresults",null);
      if(obj!=null) {
        int max=CommonUtil.toIntValue(obj,-1);
        if(max<0) throw ExceptionUtil.createException(this,null,"option [maxresults] has an invalid value ["+obj+"], value should be a number bigger or equal to 0",null);
        query.setMaxResults(max);
      }
      // offset
      obj=options.get("offset",null);
      if(obj!=null) {
        int off=CommonUtil.toIntValue(obj,-1);
        if(off<0) throw ExceptionUtil.createException(this,null,"option [offset] has an invalid value ["+obj+"], value should be a number bigger or equal to 0",null);
        query.setFirstResult(off);
      }
      // readonly
      obj=options.get("readonly",null);
      if(obj!=null) {
        Boolean ro=CommonUtil.toBoolean(obj,null);
        if(ro==null) throw ExceptionUtil.createException(this,null,"option [readonly] has an invalid value ["+obj+"], value should be a boolean value",null);
        query.setReadOnly(ro.booleanValue());
      }
      // timeout
      obj=options.get("timeout",null);
      if(obj!=null) {
        int to=CommonUtil.toIntValue(obj,-1);
        if(to<0) throw ExceptionUtil.createException(this,null,"option [timeout] has an invalid value ["+obj+"], value should be a number bigger or equal to 0",null);
        query.setTimeout(to);
      }
        }
   
   
    // params
    if(params!=null){
      QueryPlanCache cache=data.getQueryPlanCache();
      HQLQueryPlan plan = cache.getHQLQueryPlan(hql, false, java.util.Collections.EMPTY_MAP);
      ParameterMetadata meta = plan.getParameterMetadata();
      Type type;
      Object obj;
     

      // struct
      if(CommonUtil.isStruct(params)) {
        Struct sct=CommonUtil.toStruct(params);
        Key[] keys   = CommonUtil.keys(sct);
        String name;
        // fix case-senstive
        Struct names=CommonUtil.createStruct();
        if(meta!=null){
          Iterator<String> it = meta.getNamedParameterNames().iterator();
          while(it.hasNext()){
            name=it.next();
            names.setEL(name, name);
          }
        }
       
        RefBoolean isArray=CommonUtil.createRefBoolean();
        for(int i=0;i<keys.length;i++){
          obj=sct.get(keys[i],null);
          if(meta!=null){
            name=(String) names.get(keys[i],null);
            if(name==null) continue; // param not needed will be ignored
            type = meta.getNamedParameterExpectedType(name);
            obj=HibernateCaster.toSQL(type, obj,isArray);
            if(isArray.toBooleanValue())
              query.setParameterList(name, (Object[])obj,type);
            else
              query.setParameter(name, obj,type);
           
           
          }
          else
            query.setParameter(keys[i].getString(), obj);
        }
      }
     
      // array
      else if(CommonUtil.isArray(params)){
        Array arr=CommonUtil.toArray(params);
        Iterator it = arr.valueIterator();
        int index=0;
        SQLItem item;
        RefBoolean isArray=null;
        while(it.hasNext()){
          obj=it.next();
          if(obj instanceof SQLItem) {
            item=(SQLItem) obj;
            obj=item.getValue();
            //HibernateCaster.toHibernateType(item.getType(), null); MUST
            //query.setParameter(index, item.getValue(),type);
          }
          if(meta!=null){
            type = meta.getOrdinalParameterExpectedType(index+1);
            obj=HibernateCaster.toSQL(type, obj,isArray);
            // TOOD can the following be done somehow
            //if(isArray.toBooleanValue())
            //  query.setParameterList(index, (Object[])obj,type);
            //else
              query.setParameter(index, obj,type);
          }
          else
            query.setParameter(index, obj);
          index++;
        }
        if(meta.getOrdinalParameterCount()>index)
          throw ExceptionUtil.createException(this,null,"parameter array is to small ["+arr.size()+"], need ["+meta.getOrdinalParameterCount()+"] elements",null);
      }
    }
   
   
   
    // select
    String lcHQL = hql.toLowerCase();
    if(lcHQL.startsWith("select") || lcHQL.startsWith("from")){
      if(unique){
        return uniqueResult(query);
      }
     
      return query.list();
    }
      // update
    return new Double(query.executeUpdate());
  }
 
 
 
  private Object uniqueResult(org.hibernate.Query query) throws PageException {
    try{
      return query.uniqueResult();
    }
    catch(NonUniqueResultException e){
      List list = query.list();
      if(list.size()>0) return list.iterator().next();
      throw CommonUtil.toPageException(e);
    }
    catch(Throwable t){
      throw CommonUtil.toPageException(t);
    }
  }

  @Override
  public railo.runtime.type.Query toQuery(PageContext pc, Object obj, String name) throws PageException {
    return HibernateCaster.toQuery(pc,this,obj,name);
  }
 
  @Override
  public void close(PageContext pc) throws PageException {
    session().close();
    CommonUtil.releaseDatasourceConnection(pc, dc);
    dc=null;
  }
 
  @Override
  public Component merge(PageContext pc, Object obj) throws PageException {
    Component cfc = HibernateCaster.toComponent(obj);
   
    data.checkExistent(pc,cfc);
   
    String name=HibernateCaster.getEntityName(cfc);
   
    //Session session = getSession(pc, cfc);
        return CommonUtil.toComponent(session().merge(name, cfc));
  }
 

  @Override
  public Component load(PageContext pc, String name, Struct filter) throws PageException {
    return (Component) load(pc, name, filter, null, null, true);
  }

  @Override
  public Array loadAsArray(PageContext pc, String name, Struct filter) throws PageException {
    return loadAsArray(pc, name, filter,null,null);
  }
 
  @Override
  public Array loadAsArray(PageContext pc, String name, String id, String order) throws PageException{
    return loadAsArray(pc, name, id);// order is ignored in this case ACF compatibility
  }
 
  @Override
  public Array loadAsArray(PageContext pc, String name, String id) throws PageException {
    Array arr=CommonUtil.createArray();
    Component c = load(pc, name, id);
    if(c!=null)arr.append(c);
    return arr;
  }
 
  @Override
  public Array loadAsArray(PageContext pc, String name, Struct filter, Struct options) throws PageException {
    return loadAsArray(pc, name, filter,options,null);
  }
 
  @Override
  public Array loadAsArray(PageContext pc, String name, Struct filter, Struct options, String order) throws PageException {
    return CommonUtil.toArray(load(pc, name, filter, options, order, false));
  }
 
  @Override
  public Component load(PageContext pc, String cfcName, String id) throws PageException {
    //Component cfc = create(pc,cfcName);
   
   
    Component cfc=data.getEngine().create(pc, this,cfcName,false);
   
    String name = HibernateCaster.getEntityName(cfc);
    Object obj=null;
    try{
      ClassMetadata metaData = getSessionFactory(pc).getClassMetadata(name);
      if(metaData==null) throw ExceptionUtil.createException(this,null,"could not load meta information for entity ["+name+"]",null);
      Serializable oId = CommonUtil.toSerializable(
          CommonUtil.castTo(pc,
              metaData
                .getIdentifierType()
                .getReturnedClass(),
              id));
      obj=session().get(name,oId);
    }
    catch(Throwable t){
      throw CommonUtil.toPageException(t);
    }
   
    return (Component) obj;
  }
 
  @Override
  public Component loadByExample(PageContext pc, Object obj) throws PageException {
    return CommonUtil.toComponent(loadByExample(pc,obj, true));
  }
 
  @Override
  public Array loadByExampleAsArray(PageContext pc, Object obj) throws PageException {
    return CommonUtil.toArray(loadByExample(pc,obj, false));
  }
 
  private Object loadByExample(PageContext pc, Object obj,  boolean unique) throws PageException {
     Component cfc=HibernateCaster.toComponent(obj);
     ComponentScope scope = cfc.getComponentScope();
     String name=HibernateCaster.getEntityName(cfc);
     //Session session=getSession(pc, cfc);
    
     Object rtn=null;
    
     try{
      //trans.begin();
     
      ClassMetadata metaData = getSessionFactory(pc).getClassMetadata(name);
      String idName = metaData.getIdentifierPropertyName();
      Type idType = metaData.getIdentifierType();
    
      Criteria criteria=session().createCriteria(name);
      if(!Util.isEmpty(idName)){
        Object idValue = scope.get(CommonUtil.createKey(idName),null);
        if(idValue!=null){
          criteria.add(Restrictions.eq(idName, HibernateCaster.toSQL(idType, idValue,null)));
        }
      }
      criteria.add(Example.create(cfc));
      
         // execute
     
      if(!unique){
        rtn = criteria.list();
      }
      else {
        //Map map=(Map) criteria.uniqueResult();
        rtn= criteria.uniqueResult();
      }
     }
     catch(Throwable t){
      // trans.rollback();
      throw CommonUtil.toPageException(t);
     }
     //trans.commit();

     return rtn;
  }
 
 
  private Object load(PageContext pc, String cfcName, Struct filter, Struct options, String order, boolean unique) throws PageException {
    Component cfc=data.getEngine().create(pc, this,cfcName,false);
   
    String name = HibernateCaster.getEntityName(cfc);
    ClassMetadata metaData = null;
   
    Object rtn;
    try{
      //trans.begin();
     
      Criteria criteria = session().createCriteria(name);
     
      // filter
      if(filter!=null && !filter.isEmpty()){
        metaData = getSessionFactory(pc).getClassMetadata(name);
        Object value;
        Entry<Key, Object> entry;
        Iterator<Entry<Key, Object>> it = filter.entryIterator();
        String colName;
        while(it.hasNext()){
          entry = it.next();
          colName=HibernateUtil.validateColumnName(metaData, CommonUtil.toString(entry.getKey()));
          Type type = HibernateUtil.getPropertyType(metaData,colName,null);
          value=HibernateCaster.toSQL(type,entry.getValue(),null);
          if(value!=nullcriteria.add(Restrictions.eq(colName, value));
          else       criteria.add(Restrictions.isNull(colName));
        }
      }
     
      // options
      boolean ignoreCase=false;
      if(options!=null && !options.isEmpty()){
        // ignorecase
        Boolean ignorecase=CommonUtil.toBoolean(options.get("ignorecase",null),null);
            if(ignorecase!=null)ignoreCase=ignorecase.booleanValue();
           
        // offset
        int offset=CommonUtil.toIntValue(options.get("offset",null),0);
        if(offset>0) criteria.setFirstResult(offset);
           
        // maxResults
        int max=CommonUtil.toIntValue(options.get("maxresults",null),-1);
        if(max>-1) criteria.setMaxResults(max);
           
        // cacheable
        Boolean cacheable=CommonUtil.toBoolean(options.get("cacheable",null),null);
            if(cacheable!=null)criteria.setCacheable(cacheable.booleanValue());
           
            // MUST cacheName ?
           
        // maxResults
        int timeout=CommonUtil.toIntValue(options.get("timeout",null),-1);
        if(timeout>-1) criteria.setTimeout(timeout);
      }
     
      // order
      if(!Util.isEmpty(order)){
        if(metaData==null)metaData = getSessionFactory(pc).getClassMetadata(name);
       
        String[] arr = CommonUtil.toStringArray(order, ',');
        CommonUtil.trimItems(arr);
            String[] parts;
            String col;
            boolean isDesc;
            Order _order;
            //ColumnInfo ci;
            for(int i=0;i<arr.length;i++) {
              parts=CommonUtil.toStringArray(arr[i]" \t\n\b\r");
              CommonUtil.trimItems(parts);
                col=parts[0];
               
                col=HibernateUtil.validateColumnName(metaData, col);
          isDesc=false;
          if(parts.length>1){
            if(parts[1].equalsIgnoreCase("desc"))isDesc=true;
            else if(!parts[1].equalsIgnoreCase("asc")){
              throw ExceptionUtil.createException((ORMSession)null,null,"invalid order direction defintion ["+parts[1]+"]","valid values are [asc, desc]");
            }
           
          }
          _order=isDesc?Order.desc(col):Order.asc(col);
                if(ignoreCase)_order.ignoreCase();
               
                criteria.addOrder(_order);
               
            }
      }
     
      // execute
      if(!unique){
        rtn = HibernateCaster.toCFML(criteria.list());
      }
      else {
        rtn= HibernateCaster.toCFML(criteria.uniqueResult());
      }
     
     
    }
    catch(Throwable t){
      throw CommonUtil.toPageException(t);
    }
   
    return rtn;
  }
 
 
 

  @Override
  public Session getRawSession() {
    return session();
  }

  @Override
  public boolean isValid() {
    return session()!=null && session().isOpen();
  }

  @Override
  public ORMTransaction getTransaction(boolean autoManage) {
    return new HibernateORMTransaction(session(),autoManage);
  }
 
  @Override
  public DataSource getDataSource(){
    if(dc==null) {
      return data.getDataSource();
    }
    return dc.getDatasource();
  }

  @Override
  public String[] getEntityNames() {
    return data.getEntityNames();
  }
}
TOP

Related Classes of railo.runtime.orm.hibernate.HibernateORMSession

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.