protected void test() throws Throwable {
   // query to read emp_1
   ReadObjectQuery query = new ReadObjectQuery(Employee.class);
   ExpressionBuilder builder = query.getExpressionBuilder();
   Expression exp =
       builder.get("firstName").equal(firstName).and(builder.get("lastName").equal("1"));
   query.setSelectionCriteria(exp);
   // executing the query used to cause StackOverflow
   Employee empRead = (Employee) getSession().executeQuery(query);
   // the following line is provided just in case you need to put a break point after query
   // execution
   empRead.getManagedEmployees().size();
   query = null;
 }
  protected void setup() throws Throwable {
    if ((batchType == BatchFetchType.IN) && !getSession().getPlatform().isOracle()) {
      throwWarning("Nested arrays not supported on this database");
    }
    // set readBatch to true on managedEmployees mapping
    mappingToDisableBatchReadInReset =
        (ForeignReferenceMapping)
            getSession()
                .getDescriptor(Employee.class)
                .getMappingForAttributeName("managedEmployees");
    if (mappingToDisableBatchReadInReset.shouldUseBatchReading()) {
      // nothing to do - it already uses batch reading
      mappingToDisableBatchReadInReset = null;
    } else {
      mappingToDisableBatchReadInReset.setUsesBatchReading(true);
      mappingToDisableBatchReadInReset.setBatchFetchType(batchType);
      mappingToDisableBatchReadInReset.getSelectionQuery().setIsPrepared(false);
      ((ReadAllQuery) mappingToDisableBatchReadInReset.getSelectionQuery())
          .setBatchFetchPolicy(null);
      mappingToDisableBatchReadInReset
          .getDescriptor()
          .getObjectBuilder()
          .initializeBatchFetchedAttributes();
    }

    // create objects to be used by the test:
    // emp_1 has two managed employees, each of them has one managed employee.
    emp_1 = new Employee();
    emp_1.firstName = firstName;
    emp_1.lastName = "1";
    emp_1.sex = "male";
    emp_1.managedEmployees = new Vector(2);

    Employee emp_1_1 = new Employee();
    emp_1_1.firstName = firstName;
    emp_1_1.lastName = "1_1";
    emp_1_1.sex = "male";
    emp_1_1.managedEmployees = new Vector(1);
    emp_1.managedEmployees.add(emp_1_1);
    emp_1_1.manager = emp_1;

    Employee emp_1_2 = new Employee();
    emp_1_2.firstName = firstName;
    emp_1_2.lastName = "1_2";
    emp_1_2.sex = "male";
    emp_1_2.managedEmployees = new Vector(1);
    emp_1.managedEmployees.add(emp_1_2);
    emp_1_2.manager = emp_1;

    Employee emp_1_1_1 = new Employee();
    emp_1_1_1.firstName = firstName;
    emp_1_1_1.lastName = "1_1_1";
    emp_1_1_1.sex = "male";
    emp_1_1.managedEmployees.add(emp_1_1_1);
    emp_1_1_1.manager = emp_1_1;

    Employee emp_1_2_1 = new Employee();
    emp_1_2_1.firstName = firstName;
    emp_1_2_1.lastName = "1_2_1";
    emp_1_2_1.sex = "male";
    emp_1_2.managedEmployees.add(emp_1_2_1);
    emp_1_2_1.manager = emp_1_2;

    // Begin transaction here and rollback it in reset.
    ((AbstractSession) getSession()).beginTransaction();

    // write the objects into the db, merge them into session's cache.
    UnitOfWork uow = getSession().acquireUnitOfWork();
    uow.registerObject(emp_1);
    uow.commit();

    // now invalidate all the created objects in the session's cache
    getSession().getIdentityMapAccessor().invalidateObject(emp_1);
    getSession().getIdentityMapAccessor().invalidateObject(emp_1_1);
    getSession().getIdentityMapAccessor().invalidateObject(emp_1_2);
    getSession().getIdentityMapAccessor().invalidateObject(emp_1_1_1);
    getSession().getIdentityMapAccessor().invalidateObject(emp_1_2_1);
  }