/** {@inheritDoc} */
  @Override
  public void txEnd(GridCacheTx tx, boolean commit) throws GridException {
    init();

    Session ses = tx.removeMeta(ATTR_SES);

    if (ses != null) {
      Transaction hTx = ses.getTransaction();

      if (hTx != null) {
        try {
          if (commit) {
            ses.flush();

            hTx.commit();
          } else hTx.rollback();

          if (log.isDebugEnabled())
            log.debug("Transaction ended [xid=" + tx.xid() + ", commit=" + commit + ']');
        } catch (HibernateException e) {
          throw new GridException(
              "Failed to end transaction [xid=" + tx.xid() + ", commit=" + commit + ']', e);
        } finally {
          ses.close();
        }
      }
    }
  }
  /**
   * Ends hibernate session.
   *
   * @param ses Hibernate session.
   * @param tx Cache ongoing transaction.
   */
  private void end(Session ses, GridCacheTx tx) {
    // Commit only if there is no cache transaction,
    // otherwise txEnd() will do all required work.
    if (tx == null) {
      Transaction hTx = ses.getTransaction();

      if (hTx != null && hTx.isActive()) hTx.commit();

      ses.close();
    }
  }
  private List listEvents() {

    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    session.beginTransaction();

    List result = session.createQuery("from Event").list();

    session.getTransaction().commit();

    return result;
  }
  private void addEmailToPerson(Long personId, String emailAddress) {

    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    session.beginTransaction();

    Person aPerson = (Person) session.load(Person.class, personId);

    // The getEmailAddresses() might trigger a lazy load of the collection
    aPerson.getEmailAddresses().add(emailAddress);

    session.getTransaction().commit();
  }
  private void addPersonToEvent(Long personId, Long eventId) {

    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    session.beginTransaction();

    Person aPerson =
        (Person)
            session
                .createQuery("select p from Person p left join fetch p.events where p.id = :pid")
                .setParameter("pid", personId)
                .uniqueResult(); // Eager fetch the collection so we can use it detached

    Event anEvent = (Event) session.load(Event.class, eventId);
    // If we want to handle it bidirectional and detached, we also need to load this
    // collection with an eager outer-join fetch, this time with Criteria and not HQL:
    /*
    Event anEvent = (Event) session
            .createCriteria(Event.class).setFetchMode("participants", FetchMode.JOIN)
            .add( Expression.eq("id", eventId) )
            .uniqueResult(); // Eager fetch the colleciton so we can use it detached
    */

    session.getTransaction().commit();

    // End of first unit of work

    aPerson.getEvents().add(anEvent); // aPerson is detached
    // or bidirectional safety method, setting both sides: aPerson.addToEvent(anEvent);

    // Begin second unit of work

    Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();
    session2.beginTransaction();

    session2.update(aPerson); // Reattachment of aPerson

    session2.getTransaction().commit();
  }
  private Long createAndStorePerson(String firstname, String lastname) {

    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    session.beginTransaction();

    Person thePerson = new Person();
    thePerson.setFirstname(firstname);
    thePerson.setLastname(lastname);

    session.save(thePerson);

    session.getTransaction().commit();

    return thePerson.getId();
  }
  private Long createAndStoreEvent(String title, Date theDate) {

    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    session.beginTransaction();

    Event theEvent = new Event();
    theEvent.setTitle(title);
    theEvent.setDate(theDate);

    session.save(theEvent);

    session.getTransaction().commit();

    return theEvent.getId();
  }