001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.orm.hibernate; 020 021import java.io.Serializable; 022import java.util.ArrayList; 023import java.util.HashMap; 024import java.util.Iterator; 025import java.util.List; 026import java.util.Map; 027import java.util.Map.Entry; 028 029import lucee.commons.lang.types.RefBoolean; 030import lucee.loader.util.Util; 031import lucee.runtime.Component; 032import lucee.runtime.ComponentScope; 033import lucee.runtime.PageContext; 034import lucee.runtime.db.DataSource; 035import lucee.runtime.db.DatasourceConnection; 036import lucee.runtime.db.SQLItem; 037import lucee.runtime.exp.PageException; 038import lucee.runtime.op.Caster; 039import lucee.runtime.orm.ORMEngine; 040import lucee.runtime.orm.ORMSession; 041import lucee.runtime.orm.ORMTransaction; 042import lucee.runtime.orm.ORMUtil; 043import lucee.runtime.type.Array; 044import lucee.runtime.type.Collection.Key; 045import lucee.runtime.type.KeyImpl; 046import lucee.runtime.type.Struct; 047import lucee.runtime.type.scope.Argument; 048 049import org.hibernate.Criteria; 050import org.hibernate.FlushMode; 051import org.hibernate.NonUniqueResultException; 052import org.hibernate.QueryException; 053import org.hibernate.Session; 054import org.hibernate.SessionFactory; 055import org.hibernate.Transaction; 056import org.hibernate.criterion.Example; 057import org.hibernate.criterion.Order; 058import org.hibernate.criterion.Restrictions; 059import org.hibernate.engine.query.HQLQueryPlan; 060import org.hibernate.engine.query.ParameterMetadata; 061import org.hibernate.engine.query.QueryPlanCache; 062import org.hibernate.metadata.ClassMetadata; 063import org.hibernate.type.Type; 064 065public class HibernateORMSession implements ORMSession { 066 067 private SessionFactoryData data; 068 //private DataSource[] sources; 069 private DatasourceConnection[] connections; 070 //private Map<DataSource,Session> _sessions=new HashMap<DataSource, Session>(); 071 072 //private Map<Key,DataSource> _sources=new HashMap<Key, DataSource>(); 073 private Map<Key,Session> _sessions=new HashMap<Key, Session>(); 074 075 public HibernateORMSession(PageContext pc,SessionFactoryData data) throws PageException{ 076 this.data=data; 077 //this.dc=dc; 078 DataSource[] sources = data.getDataSources(); 079 connections=new DatasourceConnection[sources.length]; 080 081 for(int i=0;i<sources.length;i++){ 082 connections[i]=CommonUtil.getDatasourceConnection(pc, sources[i]); 083 createSession(data.getFactory(KeyImpl.init(sources[i].getName())),connections[i]); 084 } 085 } 086 087 /*private Session session(){ 088 return _session; 089 }*/ 090 091 private Session getSession(Key datasSourceName) throws PageException{ 092 Session s = _sessions.get(datasSourceName); 093 if(s!=null) return s; 094 095 lucee.commons.lang.ExceptionUtil.similarKeyMessage( 096 _sessions.keySet().toArray(new Key[_sessions.size()]) 097 ,datasSourceName.getString(),"datasource","datasources",true); 098 099 throw ExceptionUtil.createException(data, null, "there is no Session for the datasource ["+datasSourceName+"]",null); 100 } 101 102 public SessionFactoryData getSessionFactoryData(){ 103 return data; 104 } 105 SessionFactory getSessionFactory(Key datasSourceName) throws PageException{ 106 Session s = getSession(datasSourceName); 107 return s.getSessionFactory(); 108 } 109 110 void resetSession(PageContext pc,SessionFactory factory, Key dataSourceName, SessionFactoryData data) throws PageException { 111 112 for(int i=0;i<connections.length;i++){ 113 if(dataSourceName.equals(connections[i].getDatasource().getName())) { 114 createSession(factory, connections[i]); 115 return; 116 } 117 } 118 DataSource ds = data.getDataSource(dataSourceName); 119 DatasourceConnection dc = CommonUtil.getDatasourceConnection(pc, ds); 120 try{ 121 createSession(factory, dc); 122 } 123 finally { 124 CommonUtil.releaseDatasourceConnection(pc, dc); 125 } 126 } 127 128 void createSession(SessionFactory factory, DatasourceConnection dc) { 129 Session session; 130 _sessions.put(KeyImpl.init(dc.getDatasource().getName()), session=factory.openSession(dc.getConnection())); 131 session.setFlushMode(FlushMode.MANUAL); 132 } 133 134 @Override 135 public ORMEngine getEngine() { 136 return data.getEngine(); 137 } 138 139 @Override 140 public void flushAll(PageContext pc) throws PageException { 141 // release all connections 142 for(int i=0;i<connections.length;i++) { 143 flush(pc, connections[i].getDatasource()); 144 } 145 } 146 147 @Override 148 public void flush(PageContext pc) throws PageException { 149 flush(pc, (String)null);// not simply null then it get ambgious for some compiler 150 } 151 152 @Override 153 public void flush(PageContext pc, String datasource) throws PageException { 154 flush(pc, ORMUtil.getDataSource(pc,datasource)); 155 } 156 157 158 private void flush(PageContext pc, DataSource datasource) throws PageException { 159 Key dsn = KeyImpl.init(datasource.getName()); 160 161 try { 162 getSession(dsn).flush(); 163 164 } 165 catch(Throwable t) { 166 lucee.commons.lang.ExceptionUtil.rethrowIfNecessary(t); 167 throw CommonUtil.toPageException(t); 168 } 169 170 } 171 172 @Override 173 public void delete(PageContext pc, Object obj) throws PageException { 174 if(CommonUtil.isArray(obj)){ 175 176 // convert to a usable structure 177 Map<Key,List<Component>> cfcs=new HashMap<Key, List<Component>>(); 178 { 179 Array arr = CommonUtil.toArray(obj); 180 Iterator<?> it = arr.valueIterator(); 181 Component cfc; 182 183 Key dsn; 184 List<Component> list; 185 while(it.hasNext()){ 186 cfc = HibernateCaster.toComponent(it.next()); 187 dsn = KeyImpl.init(ORMUtil.getDataSourceName(pc, cfc)); 188 list = cfcs.get(dsn); 189 if(list==null)cfcs.put(dsn, list=new ArrayList<Component>()); 190 list.add(cfc); 191 } 192 } 193 194 195 Iterator<Entry<Key, List<Component>>> it = cfcs.entrySet().iterator(); 196 while(it.hasNext()){ 197 Entry<Key, List<Component>> e = it.next(); 198 Transaction trans = getSession(e.getKey()).getTransaction(); 199 if(trans.isActive()) trans.begin(); 200 else trans=null; 201 202 try{ 203 Iterator<Component> _it = e.getValue().iterator(); 204 while(_it.hasNext()){ 205 _delete(pc,_it.next(),e.getKey()); 206 } 207 } 208 catch(Throwable t){ 209 lucee.commons.lang.ExceptionUtil.rethrowIfNecessary(t); 210 if(trans!=null)trans.rollback(); 211 throw CommonUtil.toPageException(t); 212 } 213 if(trans!=null)trans.commit(); 214 } 215 } 216 else _delete(pc,HibernateCaster.toComponent(obj),null); 217 } 218 219 public void _delete(PageContext pc, Component cfc, Key dsn) throws PageException { 220 if(dsn==null)dsn = KeyImpl.init(ORMUtil.getDataSourceName(pc, cfc)); 221 data.checkExistent(pc,cfc); 222 try{ 223 getSession(dsn).delete(HibernateCaster.getEntityName(cfc), cfc); 224 } 225 catch(Throwable t){ 226 lucee.commons.lang.ExceptionUtil.rethrowIfNecessary(t); 227 throw CommonUtil.toPageException(t); 228 } 229 } 230 231 232 233 @Override 234 public void save(PageContext pc, Object obj,boolean forceInsert) throws PageException { 235 Component cfc = HibernateCaster.toComponent(obj); 236 String name = HibernateCaster.getEntityName(cfc); 237 Key dsn = KeyImpl.init(ORMUtil.getDataSourceName(pc, cfc)); 238 239 try { 240 Session session = getSession(dsn); 241 if(forceInsert) 242 session.save(name, cfc); 243 else 244 session.saveOrUpdate(name, cfc); 245 } 246 catch(Throwable t){ 247 lucee.commons.lang.ExceptionUtil.rethrowIfNecessary(t); 248 throw ExceptionUtil.createException(this,null,t); 249 } 250 } 251 252 @Override 253 public void reload(PageContext pc,Object obj) throws PageException { 254 Component cfc = HibernateCaster.toComponent(obj); 255 Key dsn = KeyImpl.init(ORMUtil.getDataSourceName(pc, cfc)); 256 data.checkExistent(pc,cfc); 257 getSession(dsn).refresh(cfc); 258 } 259 260 261 @Override 262 public Component create(PageContext pc, String entityName)throws PageException { 263 return data.getEngine().create(pc,this, entityName,true); 264 } 265 266 @Override 267 public void clear(PageContext pc) throws PageException { 268 clear(pc, null); 269 } 270 271 272 273 @Override 274 public void clear(PageContext pc, String datasource) throws PageException { 275 Key dsn = KeyImpl.init(ORMUtil.getDataSource(pc,datasource).getName()); 276 277 getSession(dsn).clear(); 278 /*Iterator<Session> it = _sessions.values().iterator(); 279 while(it.hasNext()){ 280 it.next().clear(); 281 }*/ 282 } 283 284 @Override 285 public void evictQueries(PageContext pc) throws PageException { 286 evictQueries(pc, null,null); 287 } 288 289 @Override 290 public void evictQueries(PageContext pc,String cacheName) throws PageException { 291 evictQueries(pc, cacheName, null); 292 } 293 294 @Override 295 public void evictQueries(PageContext pc,String cacheName, String datasource) throws PageException { 296 Key dsn = KeyImpl.init(ORMUtil.getDataSource(pc,datasource).getName()); 297 SessionFactory factory = getSession(dsn).getSessionFactory(); 298 299 if(Util.isEmpty(cacheName))factory.evictQueries(); 300 else factory.evictQueries(cacheName); 301 302 /*Iterator<Session> it = _sessions.values().iterator(); 303 while(it.hasNext()){ 304 SessionFactory f = it.next().getSessionFactory(); 305 if(Util.isEmpty(cacheName))f.evictQueries(); 306 else f.evictQueries(cacheName); 307 }*/ 308 } 309 310 @Override 311 public void evictEntity(PageContext pc, String entityName) throws PageException { 312 evictEntity(pc, entityName, null); 313 } 314 315 @Override 316 public void evictEntity(PageContext pc, String entityName, String id) throws PageException { 317 Iterator<Session> it = _sessions.values().iterator(); 318 while(it.hasNext()){ 319 SessionFactory f = it.next().getSessionFactory(); 320 if(id==null) f.evictEntity(entityName); 321 else f.evictEntity(entityName,CommonUtil.toSerializable(id)); 322 } 323 } 324 325 @Override 326 public void evictCollection(PageContext pc, String entityName, String collectionName) throws PageException { 327 evictCollection(pc, entityName, collectionName, null); 328 } 329 330 @Override 331 public void evictCollection(PageContext pc, String entityName, String collectionName, String id) throws PageException { 332 String role=entityName+"."+collectionName; 333 334 Iterator<Session> it = _sessions.values().iterator(); 335 while(it.hasNext()){ 336 SessionFactory f = it.next().getSessionFactory(); 337 if(id==null) f.evictCollection(role); 338 else f.evictCollection(role,CommonUtil.toSerializable(id)); 339 } 340 } 341 342 @Override 343 public Object executeQuery(PageContext pc, String dataSourceName,String hql, Array params, boolean unique,Struct queryOptions) throws PageException { 344 return _executeQuery(pc, dataSourceName,hql, params, unique, queryOptions); 345 } 346 347 @Override 348 public Object executeQuery(PageContext pc,String dataSourceName, String hql, Struct params, boolean unique,Struct queryOptions) throws PageException { 349 return _executeQuery(pc, dataSourceName,hql, params, unique, queryOptions); 350 } 351 352 private Object _executeQuery(PageContext pc, String dataSourceName,String hql, Object params, boolean unique,Struct queryOptions) throws PageException { 353 Key dsn; 354 if(dataSourceName==null)dsn=KeyImpl.init(ORMUtil.getDefaultDataSource(pc).getName()); 355 else dsn=KeyImpl.init(dataSourceName); 356 357 Session s=getSession(dsn); 358 try{ 359 return __executeQuery(pc,s,dsn, hql, params, unique, queryOptions); 360 } 361 catch(QueryException qe) { 362 // argument scope is array and struct at the same time, by default it is handled as struct, if this fails try it as array 363 if(params instanceof Argument) { 364 try{ 365 return __executeQuery(pc, s, dsn, hql, CommonUtil.toArray((Argument)params), unique, queryOptions); 366 } 367 catch(Throwable t){ 368 lucee.commons.lang.ExceptionUtil.rethrowIfNecessary(t); 369 t.printStackTrace(); 370 } 371 } 372 throw qe; 373 } 374 375 } 376 377 private Object __executeQuery(PageContext pc, Session session,Key dsn,String hql, Object params, boolean unique,Struct options) throws PageException { 378 //Session session = getSession(pc,null); 379 hql=hql.trim(); 380 org.hibernate.Query query = session.createQuery(hql); 381 // options 382 if(options!=null){ 383 // maxresults 384 Object obj=options.get("maxresults",null); 385 if(obj!=null) { 386 int max=CommonUtil.toIntValue(obj,-1); 387 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); 388 query.setMaxResults(max); 389 } 390 // offset 391 obj=options.get("offset",null); 392 if(obj!=null) { 393 int off=CommonUtil.toIntValue(obj,-1); 394 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); 395 query.setFirstResult(off); 396 } 397 // readonly 398 obj=options.get("readonly",null); 399 if(obj!=null) { 400 Boolean ro=CommonUtil.toBoolean(obj,null); 401 if(ro==null) throw ExceptionUtil.createException(this,null,"option [readonly] has an invalid value ["+obj+"], value should be a boolean value",null); 402 query.setReadOnly(ro.booleanValue()); 403 } 404 // timeout 405 obj=options.get("timeout",null); 406 if(obj!=null) { 407 int to=CommonUtil.toIntValue(obj,-1); 408 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); 409 query.setTimeout(to); 410 } 411 } 412 413 414 // params 415 if(params!=null){ 416 QueryPlanCache cache=data.getQueryPlanCache(dsn); 417 HQLQueryPlan plan = cache.getHQLQueryPlan(hql, false, java.util.Collections.EMPTY_MAP); 418 ParameterMetadata meta = plan.getParameterMetadata(); 419 Type type; 420 Object obj; 421 422 423 // struct 424 if(CommonUtil.isStruct(params)) { 425 Struct sct=CommonUtil.toStruct(params); 426 Key[] keys = CommonUtil.keys(sct); 427 String name; 428 // fix case-senstive 429 Struct names=CommonUtil.createStruct(); 430 if(meta!=null){ 431 Iterator<String> it = meta.getNamedParameterNames().iterator(); 432 while(it.hasNext()){ 433 name=it.next(); 434 names.setEL(name, name); 435 } 436 } 437 438 RefBoolean isArray=CommonUtil.createRefBoolean(); 439 for(int i=0;i<keys.length;i++){ 440 obj=sct.get(keys[i],null); 441 if(meta!=null){ 442 name=(String) names.get(keys[i],null); 443 if(name==null) continue; // param not needed will be ignored 444 type = meta.getNamedParameterExpectedType(name); 445 obj=HibernateCaster.toSQL(type, obj,isArray); 446 if(isArray.toBooleanValue()) { 447 if(obj instanceof Object[]) 448 query.setParameterList(name, (Object[])obj,type); 449 else if(obj instanceof List) 450 query.setParameterList(name, (List)obj,type); 451 else 452 query.setParameterList(name, Caster.toList(obj),type); 453 } 454 else 455 query.setParameter(name, obj,type); 456 457 458 } 459 else 460 query.setParameter(keys[i].getString(), obj); 461 } 462 } 463 464 // array 465 else if(CommonUtil.isArray(params)){ 466 Array arr=CommonUtil.toArray(params); 467 Iterator it = arr.valueIterator(); 468 int index=0; 469 SQLItem item; 470 RefBoolean isArray=null; 471 while(it.hasNext()){ 472 obj=it.next(); 473 if(obj instanceof SQLItem) { 474 item=(SQLItem) obj; 475 obj=item.getValue(); 476 //HibernateCaster.toHibernateType(item.getType(), null); MUST 477 //query.setParameter(index, item.getValue(),type); 478 } 479 if(meta!=null){ 480 type = meta.getOrdinalParameterExpectedType(index+1); 481 obj=HibernateCaster.toSQL(type, obj,isArray); 482 // TOOD can the following be done somehow 483 //if(isArray.toBooleanValue()) 484 // query.setParameterList(index, (Object[])obj,type); 485 //else 486 query.setParameter(index, obj,type); 487 } 488 else 489 query.setParameter(index, obj); 490 index++; 491 } 492 if(meta.getOrdinalParameterCount()>index) 493 throw ExceptionUtil.createException(this,null,"parameter array is to small ["+arr.size()+"], need ["+meta.getOrdinalParameterCount()+"] elements",null); 494 } 495 } 496 497 498 499 // select 500 String lcHQL = hql.toLowerCase(); 501 if(lcHQL.startsWith("select") || lcHQL.startsWith("from")){ 502 if(unique){ 503 return uniqueResult(query); 504 } 505 506 return query.list(); 507 } 508 // update 509 return new Double(query.executeUpdate()); 510 } 511 512 513 514 private Object uniqueResult(org.hibernate.Query query) throws PageException { 515 try{ 516 return query.uniqueResult(); 517 } 518 catch(NonUniqueResultException e){ 519 List list = query.list(); 520 if(list.size()>0) return list.iterator().next(); 521 throw CommonUtil.toPageException(e); 522 } 523 catch(Throwable t){ 524 lucee.commons.lang.ExceptionUtil.rethrowIfNecessary(t); 525 throw CommonUtil.toPageException(t); 526 } 527 } 528 529 @Override 530 public lucee.runtime.type.Query toQuery(PageContext pc, Object obj, String name) throws PageException { 531 return HibernateCaster.toQuery(pc,this,obj,name); 532 } 533 @Override 534 public void close(PageContext pc) throws PageException { 535 close(pc, null); 536 } 537 @Override 538 public void close(PageContext pc, String datasource) throws PageException { 539 DataSource ds = ORMUtil.getDataSource(pc,datasource); 540 Key dsn = KeyImpl.init(ds.getName()); 541 542 // close Session 543 getSession(dsn).close(); 544 545 // release connection 546 List<DatasourceConnection> list=new ArrayList<DatasourceConnection>(); 547 for(int i=0;i<connections.length;i++){ 548 if(connections[i].getDatasource().equals(ds)) { 549 CommonUtil.releaseDatasourceConnection(pc, connections[i]); 550 } 551 else list.add(connections[i]); 552 } 553 connections=list.toArray(new DatasourceConnection[list.size()]); 554 } 555 556 @Override 557 public void closeAll(PageContext pc) throws PageException { 558 559 Iterator<Session> it = _sessions.values().iterator(); 560 while(it.hasNext()){ 561 Session s = it.next(); 562 s.close(); 563 } 564 565 // release all connections 566 for(int i=0;i<connections.length;i++){ 567 CommonUtil.releaseDatasourceConnection(pc, connections[i]); 568 } 569 connections=null; 570 } 571 572 @Override 573 public Component merge(PageContext pc, Object obj) throws PageException { 574 Component cfc = HibernateCaster.toComponent(obj); 575 CFCInfo info = data.checkExistent(pc,cfc); 576 577 String name=HibernateCaster.getEntityName(cfc); 578 579 return CommonUtil.toComponent(getSession(KeyImpl.init(info.getDataSource().getName())).merge(name, cfc)); 580 } 581 582 583 @Override 584 public Component load(PageContext pc, String name, Struct filter) throws PageException { 585 return (Component) load(pc, name, filter, null, null, true); 586 } 587 588 @Override 589 public Array loadAsArray(PageContext pc, String name, Struct filter) throws PageException { 590 return loadAsArray(pc, name, filter,null,null); 591 } 592 593 @Override 594 public Array loadAsArray(PageContext pc, String name, String id, String order) throws PageException{ 595 return loadAsArray(pc, name, id);// order is ignored in this case ACF compatibility 596 } 597 598 @Override 599 public Array loadAsArray(PageContext pc, String name, String id) throws PageException { 600 Array arr=CommonUtil.createArray(); 601 Component c = load(pc, name, id); 602 if(c!=null)arr.append(c); 603 return arr; 604 } 605 606 @Override 607 public Array loadAsArray(PageContext pc, String name, Struct filter, Struct options) throws PageException { 608 return loadAsArray(pc, name, filter,options,null); 609 } 610 611 @Override 612 public Array loadAsArray(PageContext pc, String name, Struct filter, Struct options, String order) throws PageException { 613 return CommonUtil.toArray(load(pc, name, filter, options, order, false)); 614 } 615 616 @Override 617 public Component load(PageContext pc, String cfcName, String id) throws PageException { 618 //Component cfc = create(pc,cfcName); 619 620 621 Component cfc=data.getEngine().create(pc, this,cfcName,false); 622 Key dsn = KeyImpl.init(ORMUtil.getDataSourceName(pc, cfc)); 623 Session sess = getSession(dsn); 624 String name = HibernateCaster.getEntityName(cfc); 625 Object obj=null; 626 try{ 627 ClassMetadata metaData = sess.getSessionFactory().getClassMetadata(name); 628 if(metaData==null) throw ExceptionUtil.createException(this,null,"could not load meta information for entity ["+name+"]",null); 629 Serializable oId = CommonUtil.toSerializable( 630 CommonUtil.castTo(pc, 631 metaData 632 .getIdentifierType() 633 .getReturnedClass(), 634 id)); 635 obj=sess.get(name,oId); 636 } 637 catch(Throwable t){ 638 lucee.commons.lang.ExceptionUtil.rethrowIfNecessary(t); 639 throw CommonUtil.toPageException(t); 640 } 641 642 return (Component) obj; 643 } 644 645 @Override 646 public Component loadByExample(PageContext pc, Object obj) throws PageException { 647 return CommonUtil.toComponent(loadByExample(pc,obj, true)); 648 } 649 650 @Override 651 public Array loadByExampleAsArray(PageContext pc, Object obj) throws PageException { 652 return CommonUtil.toArray(loadByExample(pc,obj, false)); 653 } 654 655 private Object loadByExample(PageContext pc, Object obj, boolean unique) throws PageException { 656 Component cfc=HibernateCaster.toComponent(obj); 657 Key dsn = KeyImpl.init(ORMUtil.getDataSourceName(pc, cfc)); 658 ComponentScope scope = cfc.getComponentScope(); 659 String name=HibernateCaster.getEntityName(cfc); 660 Session sess = getSession(dsn); 661 Object rtn=null; 662 663 try{ 664 //trans.begin(); 665 666 ClassMetadata metaData = sess.getSessionFactory().getClassMetadata(name); 667 String idName = metaData.getIdentifierPropertyName(); 668 Type idType = metaData.getIdentifierType(); 669 670 Criteria criteria=sess.createCriteria(name); 671 if(!Util.isEmpty(idName)){ 672 Object idValue = scope.get(CommonUtil.createKey(idName),null); 673 if(idValue!=null){ 674 criteria.add(Restrictions.eq(idName, HibernateCaster.toSQL(idType, idValue,null))); 675 } 676 } 677 criteria.add(Example.create(cfc)); 678 679 // execute 680 681 if(!unique){ 682 rtn = criteria.list(); 683 } 684 else { 685 //Map map=(Map) criteria.uniqueResult(); 686 rtn= criteria.uniqueResult(); 687 } 688 } 689 catch(Throwable t){ 690 lucee.commons.lang.ExceptionUtil.rethrowIfNecessary(t); 691 // trans.rollback(); 692 throw CommonUtil.toPageException(t); 693 } 694 //trans.commit(); 695 696 return rtn; 697 } 698 699 700 private Object load(PageContext pc, String cfcName, Struct filter, Struct options, String order, boolean unique) throws PageException { 701 Component cfc=data.getEngine().create(pc, this,cfcName,false); 702 Key dsn = KeyImpl.init(ORMUtil.getDataSourceName(pc, cfc)); 703 Session sess = getSession(dsn); 704 705 String name = HibernateCaster.getEntityName(cfc); 706 ClassMetadata metaData = null; 707 708 Object rtn; 709 try{ 710 //trans.begin(); 711 712 Criteria criteria = sess.createCriteria(name); 713 714 // filter 715 if(filter!=null && !filter.isEmpty()){ 716 metaData = sess.getSessionFactory().getClassMetadata(name); 717 Object value; 718 Entry<Key, Object> entry; 719 Iterator<Entry<Key, Object>> it = filter.entryIterator(); 720 String colName; 721 while(it.hasNext()){ 722 entry = it.next(); 723 colName=HibernateUtil.validateColumnName(metaData, CommonUtil.toString(entry.getKey())); 724 Type type = HibernateUtil.getPropertyType(metaData,colName,null); 725 value=entry.getValue(); 726 if(!(value instanceof Component)) 727 value=HibernateCaster.toSQL(type,value,null); 728 729 if(value!=null) criteria.add(Restrictions.eq(colName, value)); 730 else criteria.add(Restrictions.isNull(colName)); 731 } 732 } 733 734 // options 735 boolean ignoreCase=false; 736 if(options!=null && !options.isEmpty()){ 737 // ignorecase 738 Boolean ignorecase=CommonUtil.toBoolean(options.get("ignorecase",null),null); 739 if(ignorecase!=null)ignoreCase=ignorecase.booleanValue(); 740 741 // offset 742 int offset=CommonUtil.toIntValue(options.get("offset",null),0); 743 if(offset>0) criteria.setFirstResult(offset); 744 745 // maxResults 746 int max=CommonUtil.toIntValue(options.get("maxresults",null),-1); 747 if(max>-1) criteria.setMaxResults(max); 748 749 // cacheable 750 Boolean cacheable=CommonUtil.toBoolean(options.get("cacheable",null),null); 751 if(cacheable!=null)criteria.setCacheable(cacheable.booleanValue()); 752 753 // MUST cacheName ? 754 755 // maxResults 756 int timeout=CommonUtil.toIntValue(options.get("timeout",null),-1); 757 if(timeout>-1) criteria.setTimeout(timeout); 758 } 759 760 // order 761 if(!Util.isEmpty(order)){ 762 if(metaData==null)metaData = sess.getSessionFactory().getClassMetadata(name); 763 764 String[] arr = CommonUtil.toStringArray(order, ','); 765 CommonUtil.trimItems(arr); 766 String[] parts; 767 String col; 768 boolean isDesc; 769 Order _order; 770 //ColumnInfo ci; 771 for(int i=0;i<arr.length;i++) { 772 parts=CommonUtil.toStringArray(arr[i], " \t\n\b\r"); 773 CommonUtil.trimItems(parts); 774 col=parts[0]; 775 776 col=HibernateUtil.validateColumnName(metaData, col); 777 isDesc=false; 778 if(parts.length>1){ 779 if(parts[1].equalsIgnoreCase("desc"))isDesc=true; 780 else if(!parts[1].equalsIgnoreCase("asc")){ 781 throw ExceptionUtil.createException((ORMSession)null,null,"invalid order direction defintion ["+parts[1]+"]","valid values are [asc, desc]"); 782 } 783 784 } 785 _order=isDesc?Order.desc(col):Order.asc(col); 786 if(ignoreCase)_order.ignoreCase(); 787 788 criteria.addOrder(_order); 789 790 } 791 } 792 793 // execute 794 if(!unique){ 795 rtn = HibernateCaster.toCFML(criteria.list()); 796 } 797 else { 798 rtn= HibernateCaster.toCFML(criteria.uniqueResult()); 799 } 800 801 802 } 803 catch(Throwable t){ 804 lucee.commons.lang.ExceptionUtil.rethrowIfNecessary(t); 805 throw CommonUtil.toPageException(t); 806 } 807 808 return rtn; 809 } 810 811 812 813 814 @Override 815 public Session getRawSession(String dsn) throws PageException { 816 return getSession(KeyImpl.init(dsn)); 817 } 818 819 @Override 820 public SessionFactory getRawSessionFactory(String dsn) throws PageException { 821 return getSession(KeyImpl.init(dsn)).getSessionFactory(); 822 } 823 824 @Override 825 public boolean isValid(DataSource ds) { 826 Session sess = _sessions.get(ds); 827 return sess!=null && sess.isOpen(); 828 } 829 830 @Override 831 public boolean isValid() { 832 if(_sessions.size()==0) return false; 833 Iterator<Session> it = _sessions.values().iterator(); 834 while(it.hasNext()){ 835 if(!it.next().isOpen()) return false; 836 } 837 return true; 838 } 839 840 @Override 841 public ORMTransaction getTransaction(String dsn,boolean autoManage) throws PageException { 842 return new HibernateORMTransaction(getSession(KeyImpl.init(dsn)),autoManage); 843 } 844 845 @Override 846 public String[] getEntityNames() { 847 List<String> names = data.getEntityNames(); 848 return names.toArray(new String[names.size()]); 849 } 850 851 @Override 852 public DataSource[] getDataSources() { 853 return data.getDataSources(); 854 } 855}