Date: Fri, 29 Mar 2024 08:24:05 +0000 (UTC) Message-ID: <1657486662.7699.1711700645271@ip-10-10-7-29.ec2.internal> Subject: Exported From Confluence MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_Part_7698_648741259.1711700645269" ------=_Part_7698_648741259.1711700645269 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Content-Location: file:///C:/exported.html
This is now committed to grouper HEAD. Here are the steps to start= using Hibernate3:
1. Sync and get the new jars: hibernate3.2.6, i2micom= mon, asms, cglib, c3p0, ehcache, backport-util-concurrent. Remove old= jars (e.g. hibernate.3.2.5)
2. Change the grouper.properties to use hib3 dao fact= ory
#dao.factory=3Dedu.internet2.middleware.grouper.internal.dao.hibernate.H=
ibernateDAOFactory
dao.factory=3Dedu.internet2.middleware.grouper.internal.dao.hib3.Hib3DAOFa=
ctory
3. Change the grouper.hibernate.properties to use the= hib3 ehcache, and hib3 dialect (in this example, mysql, but change this to= whatever DB driver type you are using)
#hibernate.dialect =
=3D net.=
sf.hibernate.dialect.MySQLDialect
hibernate.dialect &nb=
sp; =3D org.hib=
ernate.dialect.MySQL5Dialect
#hibernate.cache.provider_class  =
; =3D net.sf.hibernate.cache.EhCacheProvider
hibernate.cache.provider_class =
=3D org.hibernate.cache.EhCacheProvider
4. You must start using c3p0 database pooling (this i= s the only one we unit test with grouper with). This means changing t= he grouper.hibernate.properties (feel free to set the c3p0 pool settings as= you see fit. Below is a safe version which should perform fine, but = you can tune it to err on the side of performance if you like:
# Use DBCP connection pooling
#hibernate.dbcp.maxActive &=
nbsp; =3D 16
#hibernate.dbcp.maxIdle &nb=
sp; =3D 16
#hibernate.dbcp.maxWait &nb=
sp; =3D -1
#hibernate.dbcp.whenExhaustedAction =3D 1
# Use c3p0 connection pooling (since dbcp not supported in hibernate any=
more)
# ht=
tp://www.hibernate.org/214.html, http://www.hibernate.org/hib_docs/reference/en/html/session-configuration=
.html
hibernate.c3p0.max_size 16
hibernate.c3p0.min_size 0
#seconds
hibernate.c3p0.timeout 100
hibernate.c3p0.max_statements 0
hibernate.c3p0.idle_test_period 100
hibernate.c3p0.acquire_increment 1
hibernate.c3p0.validate false
5. Check your log4j.properties, if you have TRACE log= on hibernate, change to ERROR. If you have net.sf.hibernate, might w= ant to change to org.hibernate. Otherwise ignore.
log4j.logger.org.hibernate &nbs=
p; &=
nbsp; &nbs=
p; =3D ERROR, grouper_error
Hibernate / DB resources
public Map findAllAttributesByGroup(String uuid) throws GrouperDAOException { Map attrs =3D new HashMap(); try { Session hs =3D Hib3DAO.getSession(); Query qry =3D hs.createQuery("from Hib3AttributeDAO as a where a.gr= oupUuid =3D :uuid"); qry.setCacheable(false); qry.setCacheRegion(KLASS + ".FindAllAttributesByGroup"); qry.setString("uuid", uuid); Hib3AttributeDAO a; Iterator it =3D qry.iterate(); while (it.hasNext()) { a =3D (Hib3AttributeDAO) it.next(); attrs.put( a.getAttrName(), a.getValue() ); } hs.close(); } catch (HibernateException eH) { throw new GrouperDAOException( eH.getMessage(), eH ); } return attrs; }
public void addType(GroupDTO _g, GroupTypeDTO _gt) throws GrouperDAOException { try { Session hs =3D Hib3DAO.getSession(); Transaction tx =3D hs.beginTransaction(); try { hs.save( // new group-type tuple new Hib3GroupTypeTupleDAO() .setGroupUuid( _g.getUuid() ) .setTypeUuid( _gt.getUuid() ) ); hs.saveOrUpdate( Rosetta.getDAO(_g) ); // modified group tx.commit(); } catch (HibernateException eH) { tx.rollback(); throw eH; } finally { hs.close(); } } catch (HibernateException eH) { throw new GrouperDAOException( eH.getMessage(), eH ); } }
Here is how it would look with inverse of control
public void addType(final GroupDTO _g, final GroupTypeDTO _gt) throws GrouperDAOException { HibernateSession.callbackHibernateSession(HibernateTransactionType.READ= _WRITE_OR_USE_EXISTING, new HibernateHandler() { public Object callback(HibernateSession hibernateSession) { Session hs =3D hibernateSession.getSession(); hs.save( // new group-type tuple new Hib3GroupTypeTupleDAO() .setGroupUuid( _g.getUuid() ) .setTypeUuid( _gt.getUuid() ) ); hs.saveOrUpdate( Rosetta.getDAO(_g) ); // modified group //let HibernateSession commit or rollback depending on if probl= em or enclosing transaction return null; } }); }
public GroupDTO findByName(String name) throws GrouperDAOException, GroupNotFoundException { try { Session hs =3D Hib3DAO.getSession(); //TODO CH 20080209 Change this to be one query, not two to attribute = then group Query qry =3D hs.createQuery("from Hib3AttributeDAO as a where a.at= trName =3D 'name' and a.value =3D :value"); qry.setCacheable(false); qry.setCacheRegion(KLASS + ".FindByName"); qry.setString("value", name); Hib3AttributeDAO a =3D (Hib3AttributeDAO) qry.uniqueResult(); hs.close(); if (a =3D=3D null) { throw new GroupNotFoundException("Cannot find group with name: '" += name + "'"); } return this.findByUuid( a.getGroupUuid() ); } catch (HibernateException eH) { throw new GrouperDAOException( eH.getMessage(), eH ); } }
Here is how the code would look with inverse of control (notice how data= is passed in and out of the anonymous block (final params, and a return ob= ject)
public GroupDTO findByName(final String name) throws GrouperDAOException, GroupNotFoundException { Hib3AttributeDAO hib3AttributeDAO =3D (Hib3AttributeDAO)HibernateSessio= n.callbackHibernateSession( HibernateTransactionType.READONLY_OR_USE_EXISTING, new HibernateHandler() { public Object callback(HibernateSession hibernateSession) { Session hs =3D hibernateSession.getSession(); //TODO CH 20080209 Change this to be one query, not two to attr= ibute then group Query qry =3D hs.createQuery("from Hib3AttributeDAO as a wher= e a.attrName =3D 'name' and a.value =3D :value"); qry.setCacheable(false); qry.setCacheRegion(KLASS + ".FindByName"); qry.setString("value", name); Hib3AttributeDAO a =3D (Hib3AttributeDAO) qry.uniqueResult(); return a; } }); //this throws exception, keep out of GroupDTO groupDTO =3D hib3AttributeDAO =3D=3D null ? null : Hib3GroupD= AO.this.findByUuid( hib3AttributeDAO.getGroupUuid() ); //handle exceptions out of data access method... if (groupDTO =3D=3D null) { throw new GroupNotFoundException("Cannot find group with name: '" + n= ame + "'"); } return groupDTO; }
For simple database actions (mainly single actions), there is a helper f= ramework in HibernateSession to remove the need for inverse of control:
Here is the same block (note, transaction level can be configured, but t= here is an intelligent default):
public GroupDTO findByName(final String name) throws GrouperDAOException, GroupNotFoundException { Hib3AttributeDAO hib3AttributeDAO =3D HibernateSession.byHqlStatic() .createQuery("from Hib3AttributeDAO as a where a.attrName =3D 'name' = and a.value =3D :value") .setCacheable(false) .setCacheRegion(KLASS + ".FindByName") .setString("value", name).uniqueResult(Hib3AttributeDAO.class); //this throws exception, keep out of GroupDTO groupDTO =3D hib3AttributeDAO =3D=3D null ? null : Hib3GroupD= AO.this.findByUuid( hib3AttributeDAO.getGroupUuid() ); //handle exceptions out of data access method... if (groupDTO =3D=3D null) { throw new GroupNotFoundException("Cannot find group with name: '" + n= ame + "'"); } return groupDTO; }
Similarly for object based queries, there are helper classes/methods.&nb= sp; Here is an example:
public String create(GrouperSessionDTO _s) throws GrouperDAOException { try { Session hs =3D Hib3DAO.getSession(); Transaction tx =3D hs.beginTransaction(); Hib3DAO dao =3D (Hib3DAO) Rosetta.getDAO(_s); try { hs.save(dao); tx.commit(); } catch (HibernateException eH) { tx.rollback(); throw eH; } finally { hs.close(); } return dao.getId(); } catch (HibernateException eH) { throw new GrouperDAOException( eH.getMessage(), eH ); } }
This code will look like this:
public String create(GrouperSessionDTO _s) throws GrouperDAOException { Hib3DAO dao =3D (Hib3DAO) Rosetta.getDAO(_s); HibernateSession.byObjectStatic().save(dao); return dao.getId(); }
/** * run multiple logic together * @param grouperSession * @param groupName * @param groupName2 * @param displayExtension * @param groupDescription */ public void runLogic(GrouperSession grouperSession, String groupName, String groupName2, String displayExtension, String groupDescription) = { try { //insert a group Group.saveGroup(grouperSession, groupDescription, displayExtension, g= roupName, null, SaveMode.INSERT, false); //insert another group Group.saveGroup(grouperSession, groupDescription, displayExtension, g= roupName2, null, SaveMode.INSERT, false); } catch (StemNotFoundException e) { throw new RuntimeException("Stem wasnt found", e); } catch (Exception e) { throw new RuntimeException(e); } } /** * show simple transaction * @throws Exception if problem */ public void testTransaction() { final GrouperSession rootSession =3D SessionHelper.getRootSession(); final String displayExtension =3D "testing123 display"; final String groupDescription =3D "description"; final String groupName =3D "i2:a:testing123"; final String groupName2 =3D "i2:b:testing124"; try { R.populateRegistry(2, 2, 0); GrouperTest.deleteGroupIfExists(rootSession, groupName); GrouperTest.deleteGroupIfExists(rootSession, groupName2); } catch (Exception e) { throw new RuntimeException(e); } //demonstrate passing back data with final array final Integer[] someInt =3D new Integer[1]; //you can pass back one object from return String anythingString =3D (String) GrouperTransaction .callbackGrouperTransaction(new GrouperTransactionHandler() { public Object callback(GrouperTransaction grouperTransaction) throws GrouperDAOException { //everything in here will run in one transaction, note how to a= ccess "this" TestGroup0.this.runLogic(rootSession, groupName, groupName2, displayExtension, groupDescription); //pass data back from final array (if need more than just retur= n value) someInt[0] =3D 5; //if return with no exception, then it will auto-commit. //if exception was thrown it will rollback //this can be controlled manually with grouperTransaction.commi= t() //but it would be rare to have to do that //pass data back from return value return "anything"; } }); System.out.println(anythingString + ", " + someInt[0]); }