public void generateDemoData(int nCompanies, int nProjects, int nAddresses, int nDepartments, int maxProjectsPerEmployee, int maxEmployeesPerDepartment, int maxEmployeeVacations, int maxEmployeeNickNames, int maxEmployeePhones)
	{
		try
		{
			begin();
			PhoneService phoneService = lookupService(PHONE_SERVICE, PhoneService.class);
			ProjectService projectService = lookupService(PROJECT_SERVICE, ProjectService.class);
			EmployeeService empService = lookupService(EMPLOYEE_SERVICE, EmployeeService.class);

			List<Address> addresses = generateAddresses(nAddresses);
			List<Company> companies = generateCompanies(nCompanies, addresses);
			List<Department> departments = generateDepartments(nDepartments);
			List<Project> projects = generateProjects(nProjects);

			while (nDepartments-- > 0)
			{
				System.out.println("nDepartments -> " + nDepartments);
				int minEmployees = maxEmployeesPerDepartment >= 2 ? maxEmployeesPerDepartment / 2 : 1;

				int nEmployees = minEmployees + RAND.nextInt(maxEmployeesPerDepartment - minEmployees);
				List<ParkingSpace> parkingSpaces = generateParkingSpaces(nEmployees);
				int depId = departments.remove(0).getId();

				while (nEmployees-- > 0)
				{
					System.out.println("nEmployees -> " + nEmployees);
					String name = EMP_NAME_GEN.nextRandomName();
					float sallary = RAND.nextFloat() * 10000;
					Date hireDate = new GregorianCalendar(1990 + RAND.nextInt(new Date().getYear() + 1900 - 1990), RAND.nextInt(12), RAND.nextInt(28)).getTime();
					String desc = DESC_GENERATOR.nextRandomName();
					EmployeeType type = RAND.nextBoolean() ? EmployeeType.FULL_TIME : EmployeeType.PART_TIME;
					Company company = companies.get(RAND.nextInt(companies.size()));
					Address address = addresses.get(RAND.nextInt(addresses.size()));
					int parkingSpaceId = parkingSpaces.remove(0).getId();

					Employee employee = empService.createEmployee(name, sallary, hireDate, desc, type, company, address, depId, parkingSpaceId);

					int employeeProjects = RAND.nextInt(maxProjectsPerEmployee);
					List<Project> availableProjects = new ArrayList<>(projects);
					while (employeeProjects-- > 0)
					{
						int projectId = availableProjects.remove(RAND.nextInt(availableProjects.size())).getId();
						projectService.addEmployeeToProject(employee.getId(), projectId);
					}

					int empPhones = RAND.nextInt(maxEmployeePhones);
					List<Phone> phones = generatePhones(empPhones);

					for (Phone phone : phones)
					{
						phoneService.addPhoneToEmployee(employee.getId(), phone);
					}

					int employeeNickNames = RAND.nextInt(maxEmployeeNickNames);
					while (employeeNickNames-- > 0)
					{
						empService.addNickNameToEmployee(employee, NICK_NAME_GEN.nextRandomName());
					}

					int employeeVacations = RAND.nextInt(maxEmployeeVacations);
					while (employeeVacations-- > 0)
					{
						GregorianCalendar vacationStart = new GregorianCalendar();
						vacationStart.setTime(hireDate);
						vacationStart.add(GregorianCalendar.DAY_OF_YEAR, RAND.nextInt(100));

						VacationEntry entry = new VacationEntry(vacationStart.getTime(), RAND.nextInt(10) + 1);
						empService.addVacationToEmployee(employee, entry);
					}
				}		
			}
			commit();
		}
		catch(Throwable e)
		{
			e.printStackTrace();
			rollback();
			throw e;
		}
	}