Demo models‎ > ‎

Job applications

Workers sending out applications to vacancies: an example of many-to-many relationships (many vacancies applied for by any worker, many applications received by any vacancy) and how to persist them in the database, with linked tables that facilitate subsequent analysis.

By Matteo Richiardi and Michele Sonnessa (2014)


  • persists both periodic information (the characteristics of the population in each period, one record per worker per period) and one-off summary data (the complete history of each application / vacancy, one record per application / vacancy saved when simulation ends)

The model shows how to persist many-to-many relationships.

In the model there are unemployed workers who apply for vacancies. Every day, each unemployed worker sends a number applicationsPerPeriod of applications. Every day, a number newVacanciesPerPeriod of new vacancies is opened. Each vacancy remains open for vacancyDuration days, and collects applicants. When the vacancy is finally closed, an applicant is chosen randomly. To keep things simple, employment relationships only last for one period, after which the worker starts again as unemployed. Vacancies have lists of applicants, and unemployed workers have lists of vacancies they have applied to. These lists are annotated as @Transient (failure to do this would produce an error, as the JAS-mine persistence engine does not know how to persist collections). 

Persistence is achieved by introducing an Application class, which contains a pointer to the vacancy and the worker, a date when the application was sent, a date when the application was closed (either because another worker was selected, or because the applicant withdrew the application after finding another job), and an outcome (successful / unsuccessful / still open). Each application refers to one and only one link between a vacancy and a worker, and each link consists in one and only one application. Persistence follows easily.

The model persists three tables in the database:
  • panel data for workers (one record per worker per period) with the worker’s status;
  • a summary table with info on all the applications issued (one record per application);
  • a summary table with info on all vacancies opened (one record per vacancy).

The panel is updated at every period by the Collector upon the event DumpPeriodicInfo:

    (long) SimulationEngine.getInstance().getCurrentRunNumber(),
    ((ApplicationsModel) getManager()).getWorkerList());

The summary tables are produced only at the end of the simulation upon the event DumpOneOffInfo:

    (long) SimulationEngine.getInstance().getCurrentRunNumber(),
    ((ApplicationsModel) getManager()).getVacancyList());DatabaseUtils.snap(DatabaseUtils.getOutEntityManger(),
    (long) SimulationEngine.getInstance().getCurrentRunNumber(),
    ((ApplicationsModel) getManager()).getApplicationList());

The event is triggered when the simulation is stopped by the method

public void onEngineEvent(SystemEventType event) {
    if (event.equals(SystemEventType.Stop))

Note that the info saved in the database refer to three different entities (workers, vacancies and applications) and are characterized by to two different data structure (panel vs. population): however, thanks to the JAS-mine persistence engine the appropriate keys are automatically added: this results in linked tables which can be easily manipulated in the subsequent analysis.

Executable versions of the demo models can be found at

The source code repository is available on GitHub at, or can be downloaded by clicking on the download arrow on the bottom of this page on the right-hand side.
JAS-mine Simulation,
Mar 14, 2016, 1:44 PM