In JPA, mapping information of an entity must be accessible to the ORM provider at runtime, so that when it is writing the data to storage, mapping information can be obtained from the entity instance. Similarly, when the entity state is loaded from the storage, the provider runtime must be able to map the data into a new entity instance.
The access modes define how the persistence provider accesses the state of an entity. There are three main access modes: Field Access, Property Access, and Mixed Access. These access modes determine whether JPA uses the entity’s fields or its getter and setter methods to interact with the database.
By default, the access type is defined by the place where we put the identifier annotation (@Id). If we put it on the field – it will be AccessType.FIELD, if we put it on the getter – it will be AccessType.PROPERTY.
Let’s learn about these access modes in this tutorial.
1. Field Access Mode
Field access mode tells the JPA provider to access the entity’s fields directly. JPA uses reflection to read and write the fields directly, and the getter and setter methods are ignored.
To declare field access mode, explicitly annotate the entity with “@Access(AccessType.FIELD)“. Otherwise annotating the fields of the entity will cause the provider to use field access to get and set the state of the entity.
@Entity
@Access(AccessType.FIELD) //Use this to mention the mode explicitly
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
// other fields, getters, setters
}
- Please note that getter and setter methods might or might not be present, but if they are present, they are ignored by the provider.
- All fields must be declared as either protected, package, or private.
- Public fields are disallowed because it would open up the state fields to access by any unprotected class in the JVM.
If getter and setter methods are ignored then can we skip them from entities having field access mode?
No, because other classes in the application need to access those data fields, and access should always be given using public methods (though not necessarily getters and setters). That’s why, for convenience, we create getter and setter methods.
2. Property Access Mode
Property access mode implies the JPA provider accessing the entity’s state through its getter and setter methods. These methods can be used for encapsulation and additional logic as well.
To declare property access mode, explicitly annotate the entity with “@Access(AccessType.PROPERTY)“, or mapping annotations for a property must be on the getter method.
@Entity
public class Employee
{
private long id;
private long income;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId() { return id; }
public void setId(long id) { this.id= id; }
public long getSalary() { return income; }
public void setSalary(long salary) { this.income = salary; }
}
- When property access mode is used, the same contract as for JavaBeans applies, and there must be getter and setter methods for the persistent properties.
- The type of property is determined by the return type of the getter method and must be the same as the type of the single parameter passed into the setter method.
- Both methods must be either public or protected visibility. The mapping annotations for a property must be on the getter method.
In the above example, the Employee class has an @Id annotation on the getId()
getter method so the provider will use property access to get and set the state of the entity.
Note that the salary property (which will be mapped to the SALARY column in the database) is backed by the income field, which does not share the same name. This goes unnoticed by the provider because by specifying property access, we are telling the provider to ignore the entity fields and use only the getter and setter methods for naming.
3. Mixed Access Mode
Though you will not be required the mixed mode in most of the scenarios, it is possible and useful in some cases. Mixed access mode allows the use of both field and property access within the same entity.
In mixed access mode:
- Annotations are placed on both fields and getter methods.
- We must clearly define which fields use which access mode to avoid conflicts.
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private long income;
public long getId() { return id; }
public void setId(long id) { this.id= id; }
@Access(AccessType.PROPERTY)
public long getSalary() { return income; }
public void setSalary(long salary) { this.income = salary; }
}
Another example is when an entity subclass is added to an existing hierarchy that uses a different access type.
Adding an @Access
annotation with a specified access mode on the subclass entity (or even field) will cause the default access type to be overridden for that entity subclass.
Happy Learning !!
Comments