001    package railo.runtime.orm.hibernate;
002    
003    import java.io.Serializable;
004    import java.util.Iterator;
005    import java.util.List;
006    import java.util.Map;
007    import java.util.Map.Entry;
008    
009    import org.hibernate.Criteria;
010    import org.hibernate.FlushMode;
011    import org.hibernate.NonUniqueResultException;
012    import org.hibernate.QueryException;
013    import org.hibernate.Session;
014    import org.hibernate.SessionFactory;
015    import org.hibernate.Transaction;
016    import org.hibernate.criterion.Example;
017    import org.hibernate.criterion.Order;
018    import org.hibernate.criterion.Restrictions;
019    import org.hibernate.engine.query.HQLQueryPlan;
020    import org.hibernate.engine.query.ParameterMetadata;
021    import org.hibernate.engine.query.QueryPlanCache;
022    import org.hibernate.exception.ConstraintViolationException;
023    import org.hibernate.metadata.ClassMetadata;
024    import org.hibernate.type.Type;
025    
026    import railo.commons.lang.StringUtil;
027    import railo.commons.lang.types.RefBoolean;
028    import railo.commons.lang.types.RefBooleanImpl;
029    import railo.runtime.Component;
030    import railo.runtime.ComponentPro;
031    import railo.runtime.ComponentScope;
032    import railo.runtime.PageContext;
033    import railo.runtime.config.ConfigWebImpl;
034    import railo.runtime.db.DatasourceConnection;
035    import railo.runtime.db.SQLItem;
036    import railo.runtime.exp.PageException;
037    import railo.runtime.exp.PageExceptionImpl;
038    import railo.runtime.op.Caster;
039    import railo.runtime.op.Decision;
040    import railo.runtime.orm.ORMEngine;
041    import railo.runtime.orm.ORMException;
042    import railo.runtime.orm.ORMSession;
043    import railo.runtime.orm.ORMTransaction;
044    import railo.runtime.type.Array;
045    import railo.runtime.type.ArrayImpl;
046    import railo.runtime.type.Collection;
047    import railo.runtime.type.Collection.Key;
048    import railo.runtime.type.KeyImpl;
049    import railo.runtime.type.Struct;
050    import railo.runtime.type.StructImpl;
051    import railo.runtime.type.scope.Argument;
052    import railo.runtime.type.scope.ArgumentImpl;
053    import railo.runtime.type.util.ArraySupport;
054    import railo.runtime.type.util.ArrayUtil;
055    import railo.runtime.type.util.ComponentUtil;
056    
057    public class HibernateORMSession implements ORMSession{
058    
059            private HibernateORMEngine engine;
060            private Session _session;
061            private DatasourceConnection dc;
062    
063            public HibernateORMSession(HibernateORMEngine engine, SessionFactory factory, DatasourceConnection dc){
064                    this.engine=engine;
065                    this.dc=dc;
066                    resetSession(factory);
067                    //this._session=session;
068            }
069            
070            private Session session(){
071                    return _session;
072            }
073    
074            private SessionFactory getSessionFactory(PageContext pc){
075                    // engine.getSessionFactory(pc);
076                    return _session.getSessionFactory();
077            }
078            SessionFactory getSessionFactory(){
079                    // engine.getSessionFactory(pc);
080                    return _session.getSessionFactory();
081            }
082            
083            void resetSession(SessionFactory factory) {
084                    _session = factory.openSession(dc.getConnection());
085                    _session.setFlushMode(FlushMode.MANUAL);
086            }
087    
088            
089    
090            /**
091             * @see railo.runtime.orm.ORMSession#getDatasourceConnection()
092             */
093            public DatasourceConnection getDatasourceConnection() {
094                    return dc;
095            }
096            
097    
098            /**
099             * @see railo.runtime.orm.ORMSession#getEngine()
100             */
101            public ORMEngine getEngine() {
102                    return engine;
103            }
104            
105            /** 
106             * @see railo.runtime.orm.ORMSession#flush(railo.runtime.PageContext)
107             */
108            public void flush(PageContext pc) throws PageException {
109                    try {
110                            session().flush();
111                    }
112                    catch(ConstraintViolationException cve){
113                            PageException pe = HibernateException.toPageException(engine, cve);
114                            if(pe instanceof PageExceptionImpl && !StringUtil.isEmpty(cve.getConstraintName())) {
115                                    //print.o(cve.getConstraintName());
116                                    ((PageExceptionImpl)pe).setAdditional("constraint name", cve.getConstraintName() );
117                            }
118                            throw pe;
119                    }
120                    
121            }
122    
123            /**
124             * @see railo.runtime.orm.ORMSession#delete(railo.runtime.PageContext, java.lang.Object)
125             */
126            public void delete(PageContext pc, Object obj) throws PageException {
127                    if(Decision.isArray(obj)){
128                            Transaction trans = session().getTransaction();
129                            if(trans.isActive()) trans.begin();
130                            else trans=null;
131                            
132                            try{
133                                    Iterator it = Caster.toArray(obj).valueIterator();
134                                    while(it.hasNext()){
135                                            _delete(pc,HibernateCaster.toComponent(it.next()));
136                                    }
137                            }
138                            catch(Throwable t){
139                                    if(trans!=null)trans.rollback();
140                                    throw Caster.toPageException(t);
141                            }
142                            if(trans!=null)trans.commit();
143                    }
144                    else _delete(pc,HibernateCaster.toComponent(obj));
145            }
146            
147            public void _delete(PageContext pc, Component cfc) throws PageException {
148                    engine.checkExistent(pc,cfc);
149                    //Session session = getSession(pc,cfc);
150                    
151                    try{
152                            session().delete(HibernateCaster.getEntityName(cfc), cfc);
153                    }
154                    catch(Throwable t){
155                            throw Caster.toPageException(t);
156                    }
157            }
158            
159            
160            
161            /**
162             * @see railo.runtime.orm.ORMSession#save(railo.runtime.PageContext, java.lang.Object, boolean)
163             * TODO also supports array like delete does
164             */
165            public void save(PageContext pc, Object obj,boolean forceInsert) throws PageException {
166                    Component cfc = HibernateCaster.toComponent(obj);
167                    //Session session = getSession(pc, cfc);
168                    String name = HibernateCaster.getEntityName(cfc);
169                    try {
170                            if(forceInsert)
171                                    session().save(name, cfc);
172                            else
173                                            session().saveOrUpdate(name, cfc);
174                    }
175                    catch(Throwable t){
176                            throw HibernateException.toPageException(getEngine(), t);
177                    }
178            }
179            
180            /**
181             * @see railo.runtime.orm.ORMSession#reload(railo.runtime.PageContext, java.lang.Object)
182             */
183            public void reload(PageContext pc,Object obj) throws PageException {
184                    Component cfc = HibernateCaster.toComponent(obj);
185                    engine.checkExistent(pc,cfc);
186                    //Session session = getSession(pc,cfc);
187                    session().refresh(cfc);
188            }
189            
190    
191            /**
192             * @see railo.runtime.orm.ORMEngine#create(railo.runtime.PageContext, java.lang.String)
193             */
194            public Component create(PageContext pc, String entityName)throws PageException {
195                    return engine.create(pc,this, entityName,true);
196            }
197            
198            /**
199             * @see railo.runtime.orm.ORMSession#clear(railo.runtime.PageContext)
200             */
201            public void clear(PageContext pc) throws PageException {
202                    session().clear();
203            }
204            
205            /**
206             * @see railo.runtime.orm.ORMSession#evictQueries(railo.runtime.PageContext)
207             */
208            public void evictQueries(PageContext pc) throws PageException {
209                    evictQueries(pc, null);
210            }
211    
212            /**
213             * @see railo.runtime.orm.ORMSession#evictQueries(railo.runtime.PageContext, java.lang.String)
214             */
215            public void evictQueries(PageContext pc,String cacheName) throws PageException {
216                    SessionFactory f = getSessionFactory(pc);
217                    if(StringUtil.isEmpty(cacheName))f.evictQueries();
218                    else f.evictQueries(cacheName);
219            }
220            
221            /**
222             * @see railo.runtime.orm.ORMSession#evictEntity(railo.runtime.PageContext, java.lang.String)
223             */
224            public void evictEntity(PageContext pc, String entityName) throws PageException {
225                    evictEntity(pc, entityName, null);
226            }
227    
228            /**
229             * @see railo.runtime.orm.ORMSession#evictEntity(railo.runtime.PageContext, java.lang.String, java.lang.String)
230             */
231            public void evictEntity(PageContext pc, String entityName, String id) throws PageException {
232                    //ComponentPro cfc = ComponentUtil.toComponentPro(HibernateCaster.toComponent(pc, entityName));
233                    SessionFactory f = getSessionFactory(pc);
234                    //entityName=HibernateCaster.getEntityName(pc,engine,cfc);
235                    
236                    if(id==null) {
237                            f.evictEntity(entityName);
238                    }
239                    else {
240                            f.evictEntity(entityName,Caster.toSerializable(id));
241                    }
242            }
243            
244            /**
245             * @see railo.runtime.orm.ORMSession#evictCollection(railo.runtime.PageContext, java.lang.String, java.lang.String)
246             */
247            public void evictCollection(PageContext pc, String entityName, String collectionName) throws PageException {
248                    evictCollection(pc, entityName, collectionName, null);
249            }
250    
251            /**
252             * @see railo.runtime.orm.ORMSession#evictCollection(railo.runtime.PageContext, java.lang.String, java.lang.String, java.lang.String)
253             */
254            public void evictCollection(PageContext pc, String entityName, String collectionName, String id) throws PageException {
255                    //ComponentPro cfc = ComponentUtil.toComponentPro(HibernateCaster.toComponent(pc, entityName));
256                    //entityName=HibernateCaster.getEntityName(pc,engine,cfc);
257                    
258                    SessionFactory f = getSessionFactory(pc);
259                    String role=entityName+"."+collectionName;
260                    if(id==null) {
261                            f.evictCollection(role);
262                    }
263                    else {
264                            f.evictCollection(role,Caster.toSerializable(id));
265                    }
266            }
267            
268             
269            
270            
271            
272            
273            
274    
275            /**
276             * @see railo.runtime.orm.ORMSession#executeQuery(railo.runtime.PageContext, java.lang.String, railo.runtime.type.Array, boolean, railo.runtime.type.Struct)
277             */
278            public Object executeQuery(PageContext pc,String hql, Array params, boolean unique,Struct queryOptions) throws PageException {
279                    return _executeQuery(pc, hql, params, unique, queryOptions);
280            }
281    
282            /**
283             * @see railo.runtime.orm.ORMSession#executeQuery(railo.runtime.PageContext, java.lang.String, railo.runtime.type.Struct, boolean, railo.runtime.type.Struct)
284             */
285            public Object executeQuery(PageContext pc,String hql, Struct params, boolean unique,Struct queryOptions) throws PageException {
286                    return _executeQuery(pc, hql, params, unique, queryOptions);
287            }
288            
289            public Object _executeQuery(PageContext pc,String hql, Object params, boolean unique,Struct queryOptions) throws PageException {
290                    try{
291                            return __executeQuery(pc, hql, params, unique, queryOptions);
292                    }
293                    catch(QueryException qe) {
294                            // argument scope is array and struct at the same time, by default it is handled as struct, if this fails try it as array
295                            if(params instanceof Argument) {
296                                    try{
297                                            return __executeQuery(pc, hql, ArgumentImpl.toArray((Argument)params), unique, queryOptions);
298                                    }
299                                    catch(Throwable t){t.printStackTrace();}
300                            }
301                            throw qe;
302                    }
303                    
304                    
305            }
306            
307            private Object __executeQuery(PageContext pc,String hql, Object params, boolean unique,Struct options) throws PageException {
308                    //Session session = getSession(pc,null);
309                    hql=hql.trim();
310                    org.hibernate.Query query = session().createQuery(hql); 
311                    // options
312                    if(options!=null){
313                            // maxresults
314                            Object obj=options.get("maxresults",null);
315                            if(obj!=null) {
316                                    int max=Caster.toIntValue(obj,-1);
317                                    if(max<0) throw new ORMException(engine,"option [maxresults] has a invalid value ["+obj+"], value should be a number bigger or equal to 0");
318                                    query.setMaxResults(max);
319                            }
320                            // offset
321                            obj=options.get("offset",null);
322                            if(obj!=null) {
323                                    int off=Caster.toIntValue(obj,-1);
324                                    if(off<0) throw new ORMException(engine,"option [offset] has a invalid value ["+obj+"], value should be a number bigger or equal to 0");
325                                    query.setFirstResult(off);
326                            }
327                            // readonly
328                            obj=options.get("readonly",null);
329                            if(obj!=null) {
330                                    Boolean ro=Caster.toBoolean(obj,null);
331                                    if(ro==null) throw new ORMException(engine,"option [readonly] has a invalid value ["+obj+"], value should be a boolean value");
332                                    query.setReadOnly(ro.booleanValue());
333                            }
334                            // timeout
335                            obj=options.get("timeout",null);
336                            if(obj!=null) {
337                                    int to=Caster.toIntValue(obj,-1);
338                                    if(to<0) throw new ORMException(engine,"option [timeout] has a invalid value ["+obj+"], value should be a number bigger or equal to 0");
339                                    query.setTimeout(to);
340                            }
341            }
342                    
343                    
344                    // params
345                    if(params!=null){
346                            QueryPlanCache cache=engine.getQueryPlanCache(pc);
347                            HQLQueryPlan plan = cache.getHQLQueryPlan(hql, false, java.util.Collections.EMPTY_MAP);
348                            ParameterMetadata meta = plan.getParameterMetadata();
349                            Type type;
350                            Object obj;
351                            
352    
353                            // struct
354                            if(Decision.isStruct(params)) {
355                                    Struct sct=Caster.toStruct(params);
356                                    Key[] keys = sct.keys();
357                                    String name;
358                                    // fix case-senstive
359                                    Struct names=new StructImpl();
360                                    if(meta!=null){
361                                            Iterator<String> it = meta.getNamedParameterNames().iterator();
362                                            while(it.hasNext()){
363                                                    name=it.next();
364                                                    names.setEL(name, name);
365                                            }
366                                    }
367                                    
368                                    RefBoolean isArray=new RefBooleanImpl();
369                                    for(int i=0;i<keys.length;i++){
370                                            obj=sct.get(keys[i],null);
371                                            if(meta!=null){
372                                                    name=(String) names.get(keys[i],null);
373                                                    if(name==null) continue; // param not needed will be ignored
374                                                    type = meta.getNamedParameterExpectedType(name);
375                                                    obj=HibernateCaster.toSQL(engine, type, obj,isArray);
376                                                    if(isArray.toBooleanValue())
377                                                            query.setParameterList(name, (Object[])obj,type);
378                                                    else
379                                                            query.setParameter(name, obj,type);
380                                                    
381                                                    
382                                            }
383                                            else
384                                                    query.setParameter(keys[i].getString(), obj);
385                                    }
386                            }
387                            
388                            // array
389                            else if(Decision.isArray(params)){
390                                    Array arr=Caster.toArray(params);
391                                    Iterator it = arr.valueIterator();
392                                    int index=0;
393                                    SQLItem item;
394                                    RefBoolean isArray=null;//new RefBooleanImpl();
395                                    while(it.hasNext()){
396                                            obj=it.next();
397                                            if(obj instanceof SQLItem) {
398                                                    item=(SQLItem) obj;
399                                                    obj=item.getValue();
400                                                    //HibernateCaster.toHibernateType(item.getType(), null); MUST
401                                                    //query.setParameter(index, item.getValue(),type);
402                                            }
403                                            if(meta!=null){
404                                                    type = meta.getOrdinalParameterExpectedType(index+1);
405                                                    obj=HibernateCaster.toSQL(engine, type, obj,isArray);
406                                                    // TOOD can the following be done somehow
407                                                    //if(isArray.toBooleanValue())
408                                                    //      query.setParameterList(index, (Object[])obj,type);
409                                                    //else
410                                                            query.setParameter(index, obj,type);
411                                            }
412                                            else
413                                                    query.setParameter(index, obj);
414                                            index++;
415                                    }
416                                    if(meta.getOrdinalParameterCount()>index)
417                                            throw new ORMException(engine,"parameter array is to small ["+arr.size()+"], need ["+meta.getOrdinalParameterCount()+"] elements");
418                            }
419                    }
420                    
421                    
422                    
423                    // select
424                    if(StringUtil.startsWithIgnoreCase(hql,"select") || StringUtil.startsWithIgnoreCase(hql,"from")){
425                            if(unique){
426                                    return uniqueResult(query);
427                            }
428                            
429                            return query.list();
430                    }
431                // update
432                    return Caster.toDouble(query.executeUpdate());
433            }
434            
435            
436            
437            private Object uniqueResult(org.hibernate.Query query) {
438                    try{
439                            return query.uniqueResult();
440                    }
441                    catch(NonUniqueResultException e){
442                            List list = query.list();
443                            if(list.size()>0) return list.iterator().next();
444                            throw e;
445                    }
446            }
447    
448            /**
449             * @see railo.runtime.orm.ORMSession#toQuery(railo.runtime.PageContext, java.lang.Object, java.lang.String)
450             */
451            public railo.runtime.type.Query toQuery(PageContext pc, Object obj, String name) throws PageException {
452                    return HibernateCaster.toQuery(pc,this,obj,name);
453            }
454            
455            /**
456             * @see railo.runtime.orm.ORMSession#close(railo.runtime.PageContext)
457             */
458            public void close(PageContext pc) throws PageException {
459                    session().close();
460                    ((ConfigWebImpl)pc.getConfig()).getDatasourceConnectionPool().releaseDatasourceConnection(dc);
461            }
462            
463            /**
464             * @see railo.runtime.orm.ORMSession#merge(railo.runtime.PageContext, java.lang.Object)
465             */
466            public Component merge(PageContext pc, Object obj) throws PageException {
467                    Component cfc = HibernateCaster.toComponent(obj);
468                    
469                    engine.checkExistent(pc,cfc);
470                    
471                    String name=HibernateCaster.getEntityName(cfc);
472                    
473                    //Session session = getSession(pc, cfc);
474            try     {
475                return Caster.toComponent(session().merge(name, cfc));
476            }
477            catch(HibernateException e) {
478                    throw new ORMException(e);
479            }
480            }
481            
482    
483            /**
484             * @see railo.runtime.orm.ORMSession#load(railo.runtime.PageContext, java.lang.String, railo.runtime.type.Struct)
485             */
486            public Component load(PageContext pc, String name, Struct filter) throws PageException {
487                    return (Component) load(pc, name, filter, null, null, true);
488            }
489    
490            /**
491             * @see railo.runtime.orm.ORMSession#loadAsArray(railo.runtime.PageContext, java.lang.String, railo.runtime.type.Struct)
492             */
493            public Array loadAsArray(PageContext pc, String name, Struct filter) throws PageException {
494                    return loadAsArray(pc, name, filter,null,null);
495            }
496            
497            /**
498             * @see railo.runtime.orm.ORMSession#loadAsArray(railo.runtime.PageContext, java.lang.String, java.lang.String, java.lang.String)
499             */
500            public Array loadAsArray(PageContext pc, String name, String id, String order) throws PageException{
501                    return loadAsArray(pc, name, id);// order is ignored in this case ACF compatibility
502            }
503            
504            /**
505             * @see railo.runtime.orm.ORMSession#loadAsArray(railo.runtime.PageContext, java.lang.String, java.lang.String)
506             */
507            public Array loadAsArray(PageContext pc, String name, String id) throws PageException {
508                    Array arr=new ArrayImpl();
509                    Component c = load(pc, name, id);
510                    if(c!=null)arr.append(c);
511                    return arr;
512            }
513            
514            /**
515             * @see railo.runtime.orm.ORMSession#loadAsArray(railo.runtime.PageContext, java.lang.String, railo.runtime.type.Struct, railo.runtime.type.Struct)
516             */
517            public Array loadAsArray(PageContext pc, String name, Struct filter, Struct options) throws PageException {
518                    return loadAsArray(pc, name, filter,options,null);
519            }
520            
521            /**
522             * @see railo.runtime.orm.ORMSession#loadAsArray(railo.runtime.PageContext, java.lang.String, railo.runtime.type.Struct, railo.runtime.type.Struct, java.lang.String)
523             */
524            public Array loadAsArray(PageContext pc, String name, Struct filter, Struct options, String order) throws PageException {
525                    return Caster.toArray(load(pc, name, filter, options, order, false));
526            }
527            
528            /**
529             * @see railo.runtime.orm.ORMSession#load(railo.runtime.PageContext, java.lang.String, java.lang.String)
530             */
531            public Component load(PageContext pc, String cfcName, String id) throws PageException {
532                    //Component cfc = create(pc,cfcName);
533                    
534                    
535                    Component cfc=engine.create(pc, this,cfcName,false);
536                    
537                    String name = HibernateCaster.getEntityName(cfc);
538                    Object obj=null;
539                    try{
540                            ClassMetadata metaData = getSessionFactory(pc).getClassMetadata(name);
541                            if(metaData==null) throw new ORMException(engine,"could not load meta information for entity ["+name+"]");
542                            Serializable oId = Caster.toSerializable(
543                                            Caster.castTo(pc, 
544                                                            metaData
545                                                                    .getIdentifierType()
546                                                                    .getReturnedClass(), 
547                                                            id));
548                            obj=session().get(name,oId);
549                    }
550                    catch(Throwable t){
551                            throw Caster.toPageException(t);
552                    }
553                    
554                    return (Component) obj;
555            }
556            
557            /**
558             * @see railo.runtime.orm.ORMSession#loadByExample(railo.runtime.PageContext, java.lang.Object)
559             */
560            public Component loadByExample(PageContext pc, Object obj) throws PageException {
561                    return Caster.toComponent(loadByExample(pc,obj, true));
562            }
563            
564            /**
565             * @see railo.runtime.orm.ORMSession#loadByExampleAsArray(railo.runtime.PageContext, java.lang.Object)
566             */
567            public Array loadByExampleAsArray(PageContext pc, Object obj) throws PageException {
568                    return Caster.toArray(loadByExample(pc,obj, false));
569            }
570            
571            private Object loadByExample(PageContext pc, Object obj,  boolean unique) throws PageException {
572                     ComponentPro cfc=ComponentUtil.toComponentPro(HibernateCaster.toComponent(obj));
573                     ComponentScope scope = cfc.getComponentScope();
574                     String name=HibernateCaster.getEntityName(cfc);
575                     //Session session=getSession(pc, cfc);
576                     
577                     Object rtn=null;
578                     
579                     try{
580                            //trans.begin();
581                            
582                            ClassMetadata metaData = getSessionFactory(pc).getClassMetadata(name);
583                            String idName = metaData.getIdentifierPropertyName();
584                            Type idType = metaData.getIdentifierType();
585                     
586                            Criteria criteria=session().createCriteria(name);
587                            if(!StringUtil.isEmpty(idName)){
588                                    Object idValue = scope.get(KeyImpl.init(idName),null);
589                                    if(idValue!=null){
590                                            criteria.add(Restrictions.eq(idName, HibernateCaster.toSQL(engine, idType, idValue,null)));
591                                    }
592                            }
593                            criteria.add(Example.create(cfc));
594                 
595                    // execute
596                            
597                            if(!unique){
598                                    rtn = criteria.list();
599                            }
600                            else {
601                                    //Map map=(Map) criteria.uniqueResult();
602                                    rtn= criteria.uniqueResult();
603                            }
604                     }
605                     catch(Throwable t){
606                            // trans.rollback();
607                            throw Caster.toPageException(t);
608                     }
609                     //trans.commit();
610    
611                     return rtn;
612            }
613            
614            
615            private Object load(PageContext pc, String cfcName, Struct filter, Struct options, String order, boolean unique) throws PageException {
616                    Component cfc=engine.create(pc, this,cfcName,false);
617                    
618                    String name = HibernateCaster.getEntityName(cfc);
619                    ClassMetadata metaData = null;
620                    
621                    Object rtn;
622                    try{
623                            //trans.begin();
624                            
625                            Criteria criteria = session().createCriteria(name);
626                            
627                            // filter
628                            if(filter!=null && !filter.isEmpty()){
629                                    
630                                    metaData = getSessionFactory(pc).getClassMetadata(name);
631                                    
632                                    
633                                    
634                                    Object value;
635                                    Map.Entry entry;
636                                    Iterator it = filter.entrySet().iterator();
637                                    String colName;
638                                    while(it.hasNext()){
639                                            entry=(Entry) it.next();
640                                            colName=HibernateUtil.validateColumnName(metaData, Caster.toString(entry.getKey()));
641                                            Type type = HibernateUtil.getPropertyType(metaData,colName,null);
642                                            value=HibernateCaster.toSQL(engine,type,entry.getValue(),null);
643                                            if(value!=null) criteria.add(Restrictions.eq(colName, value));
644                                            else                    criteria.add(Restrictions.isNull(colName));
645                                            
646                                            
647                                            
648                                            
649                                    }
650                            }
651                            
652                            // options
653                            boolean ignoreCase=false;
654                            if(options!=null && !options.isEmpty()){
655                                    // ignorecase
656                                    Boolean ignorecase=Caster.toBoolean(options.get("ignorecase",null),null);
657                            if(ignorecase!=null)ignoreCase=ignorecase.booleanValue();
658                            
659                                    // offset
660                                    int offset=Caster.toIntValue(options.get("offset",null),0);
661                                    if(offset>0) criteria.setFirstResult(offset);
662                            
663                                    // maxResults
664                                    int max=Caster.toIntValue(options.get("maxresults",null),-1);
665                                    if(max>-1) criteria.setMaxResults(max);
666                            
667                                    // cacheable
668                                    Boolean cacheable=Caster.toBoolean(options.get("cacheable",null),null);
669                            if(cacheable!=null)criteria.setCacheable(cacheable.booleanValue());
670                            
671                            // MUST cacheName ?
672                            
673                                    // maxResults
674                                    int timeout=Caster.toIntValue(options.get("timeout",null),-1);
675                                    if(timeout>-1) criteria.setTimeout(timeout);
676                            }
677                            
678                            // order 
679                            if(!StringUtil.isEmpty(order)){
680                                    if(metaData==null)metaData = getSessionFactory(pc).getClassMetadata(name);
681                                    
682                                    String[] arr = railo.runtime.type.List.listToStringArray(order, ',');
683                                    railo.runtime.type.List.trimItems(arr);
684                            String[] parts;
685                            String col;
686                            boolean isDesc;
687                            Order _order;
688                            //ColumnInfo ci;
689                            for(int i=0;i<arr.length;i++) {
690                                    parts=railo.runtime.type.List.toStringArray(railo.runtime.type.List.listToArray(arr[i],  " \t\n\b\r"));
691                                    railo.runtime.type.List.trimItems(parts);
692                                col=parts[0];
693                                
694                                col=HibernateUtil.validateColumnName(metaData, col);
695                                            isDesc=false;
696                                            if(parts.length>1){
697                                                    if(parts[1].equalsIgnoreCase("desc"))isDesc=true;
698                                                    else if(!parts[1].equalsIgnoreCase("asc")){
699                                                            throw new ORMException("invalid order direction defintion ["+parts[1]+"]","valid values are [asc, desc]");
700                                                    }
701                                                    
702                                            }
703                                            _order=isDesc?Order.desc(col):Order.asc(col);
704                                if(ignoreCase)_order.ignoreCase();
705                                
706                                criteria.addOrder(_order);
707                            
708                            }
709                            }
710                            
711                            // execute
712                            if(!unique){
713                                    rtn = HibernateCaster.toCFML(criteria.list());
714                            }
715                            else {
716                                    rtn= HibernateCaster.toCFML(criteria.uniqueResult());
717                            }
718                            
719                            
720                    }
721                    catch(Throwable t){
722                            throw Caster.toPageException(t);
723                    }
724                    
725                    return rtn;
726            }
727            
728            
729            
730    
731            /**
732             * @see railo.runtime.orm.ORMSession#getRawSession()
733             */
734            public Session getRawSession() {
735                    return session();
736            }
737    
738            /**
739             * @see railo.runtime.orm.ORMSession#isValid()
740             */
741            public boolean isValid() {
742                    return session()!=null && session().isOpen();
743            }
744    
745            /**
746             * @see railo.runtime.orm.ORMSession#getTransaction(boolean)
747             */
748            public ORMTransaction getTransaction(boolean autoManage) {
749                    return new HibernateORMTransaction(session(),autoManage);
750            }
751    }