The JAS-mine platform‎ > ‎Documentation‎ > ‎Cookbook‎ > ‎

Output persistence to database

Persistence is achieved by updating a table in the relational database corresponding to a class in the simulation model. Classes to be persisted must be annotated as Entity classes:

@Entity
public class Person {
    […]
}

With such a simple operation, a table with the same name of the class is automatically added to the output database, and the class is linked to this table. When the class is dumped by the Collector, all properties which are not annotated as @Transient are persisted in the database.

To provide a unique identifier for the table entries, Entity classes must specify a PanelEntityKey (annotated as @Id), which is a three-dimensional object which identifies the agent id, the simulation time and the simulation run. These three keys uniquely identify each record in the database:

@Id
private PanelEntityKey key;
  
The ORM expects that the field names in the database are the same as the property names in the Java class, except when a different name is specified as in 
 
@Column(name="dur_in_couple")
private Integer durationInCouple;
  
Enumerations can be interpreted by the ORM both as a string and as ordinal values (0 for the first enum, 1 for the second, etc.), depending on how they are annotated:  
  
@Enumerated(EnumType.STRING)
private WorkState workState;


Persisting data to the database is controlled by the Collector, which schedules the corresponding event for a specific object or set of objects belonging to the Entity class:

DatabaseUtils.snap( ( (PersonsModel) getManager()).getPersons() );

@Transient fields

The JAS-mine persistence engine saves on the dbase all the properties of an entity class that are not defined as @Transient, plus all the variables not defined as properties but implicitly defined by getters.

@Entity classes

MUST have an empty constructor. If a superclass is involved, call to the super class constructor should be like in the Extended-Schelling example:

protected ESAgent() {
     super(null);
}


PanelEntityKeys

MUST be annotated as @Id, though the PanelEntityKey object can be given any name, and it is suggested that they are not called id (key is a better name). This is because PanelEntityKey objects contain three objects:- an id field of type Long representing the agent's id, a simultion_run field storing the number of the simulation run (also of type Long) which is useful when running many simulations in sequence as each simulation run will have a unique number, and a simulation_time field (of type Double). The fields of the PanelEntityKey are thus used to uniquely identify panel entries in the database tables.

This is why to access the agent id the method getId() has to be invoked: if the PanelEntitykey is called id, this becomes id.getId(), which is confusing. If the agent id has to be accessed from other agents, for instance to perform identity checks, the following getAgentId() method should therefore be implemented:


@Entity
public class
Agent {

    @Transient
    private static
long idCounter = 1000000;

    @Id
    private
PanelEntityKey key = new PanelEntityKey(idCounter++);

    public
Long getAgentId() {
        return key.getId();
    }

}
and then used as agent.getAgentId().

With the JAS-mine persistence engine, (pointers to) objects cannot be persisted (this has to do with the fact that the PanelEntityKey is a multiple key). Therefore, the agent's PanelEntityKey should be included as an additional variable and persisted, while the (pointer to the) object should be annotated as @Transient:


@Entity
public class Application {

    @Id
    private PanelEntityKey key;

   
@Transient
    private Worker worker;

   
@Column(name="worker_id")
    private Long workerId;

}