As mentioned earlier, EclipseLink – JPA is a persistence service, provides a mechanism to communicate with a different database vendors. That type of communication has been achieved through what has become known as annotation-based configuration, which is considered as an alternative way for doing a configuration rather than the XML. The XML-based configuration remains one of the ultimate ways that can be used to configure the platforms for a long period of time prior to annotations come into picture.
- Some annotations are used within the classes declaration, while others used with the fields. Also set of annotations have been used by the lifecycle of the JPA.
- Even though we have the ability to use the annotations within a Java Standard Edition, but also the Java Enterprise Edition has its own annotations.Even if we are coming into accessibility, the annotations is there.
- A huge amount of annotations are introduced with JPA. Annotations that would be important when we are going to implement a relationship, a mapping or a JPQL.
However, getting started into annotations requires more than understanding the way of the use. But it is important to understand concept like “persistence domain“, that would help us understanding how the JPA implementation works?
Persistence Domain defined as, it is the scope of the classes that can be persisted, which controlled by the JPA implementation. And the persistence, is the process of storing the states of the objects model into permanent storage such as a database system.
The only way that makes your classes seen by the JPA implementation is through mention them into persistence.xml file, using either <class> or <jar-file> tags.
Each referenced classes in the persistence.xml file will form what we called it a “persistence domain“.So the mapping between your different scopes (i.e. objects and the database system) should started from this point as we’ll see in the next coming few lines. And that’s the meaning of Object-Relational Mapping (ORM).
This article will introduce some of the annotations that have been used with the classes’ fields to evaluate the mapping. However, the remaining annotations will be covered into other articles.
JPA Annotations for Fields
The below are the list of annotations defined in JPA for used in the field level. Here we discuss only @Basic and @Transient which are most important.
- javax.persistence.Id(@Id)
- javax.persistence.Basic (@Basic) (Should be covered at this article)
- javax.persistence.Embedded (@Embedded)
- javax.persistence.ElementCollection (@ElementCollection)
- javax.persistence.EmbeddedId(@EmbeddedId)
- javax.persistence.Version(@Version)
- javax.persistence.Transient(@Transient) (Should be covered at this article)
@Basic Annotation
- Target: fields (Including property get methods)
- Uses: @Basic
- Arguments: fetch and optional. The default value of the fetch is EAGER and it represents the strategy for fetching data from the database. The second value that can be applied is LAZY. The EAGER strategy is a requirement on the persistence provider runtime that data should be eagerly fetched. meanwhile the LAZY strategy is a hint for the persistence runtime that the data should be fetched lazily, when it’s first accessed. The persistence implementation is permitted to eagerly fetch those properties marked as LAZY fetch. The optional is a hint about whether the value of the field or property may be null. This is a hint and is disregarded for primitive types. It is almost used once you would generate the database schema through the persistence implementation itself.
Basic annotation is the simplest type of mapping to a database column, as you have noticed, the Basic annotation can be applied to a persistent property or instance variable. instance variable means that you have ability to use @Basic on the get property of that instance variable.
By default, each properties or instance variables defined within a persistent classes would have an @Basic annotation in case their type is one of the following:
- Java primitive types
- Wrappers of the primitive types
- java.lang.String
- java.lang.BigInteger
- java.math.BigDecimal
- java.util.Date
- java.util.Calendar
- java.sql.Date
- java.sql.Time
- java.sql.Timestamp
- byte [], Byte [] , char [] , Character [] , enums and any other type that implements Serializable.
The following examples shows you a simple example of persistence domain and persistence class.By reading the persistence.xml, the JPA implementation would generate the persistence domain. Inside the created domain every properties are mapped implicitly into identical column by using the name of the property with minimal change; it is converted into Uppercase.
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="EclipseLink-JPA-Installation" transaction-type="RESOURCE_LOCAL"> <class>net.javabeat.eclipselink.data.Employee</class> <properties> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/JavaBeat"/> <property name="javax.persistence.jdbc.user" value="root"/> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> <property name="javax.persistence.jdbc.password" value="root"/> <property name="eclipselink.logging.level" value="FINEST"/> </properties> </persistence-unit> </persistence>
Employee.java
package net.javabeat.eclipselink.data; import javax.persistence.Basic; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.Id; @Entity public class Employee { @Id private int employeeId; @Basic(optional=false) private String employeeName; public int getEmployeeId() { return employeeId; } public void setEmployeeId(int employeeId) { this.employeeId = employeeId; } public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public String toString(){ return this.employeeId+" "+this.employeeName; } }
If you have deleted the Employee class from the persistence.xml, you have got the following error message at the top of the Employee class:
Class "net.javabeat.eclipselink.data.Employee" is managed, but is not listed in the persistence.xml file
Meawhile, if you have deleted the @Entity annotation, you have got the following exception at the top of the Employee class:
Class "net.javabeat.eclipselink.data.Employee" is listed in the persistence.xml file, but is not annotated
@Transient Annotation
- Target: fields (Including property get methods)
- Uses: @Transient
- Arguments:no argument was specified.
The Transient annotation is working as opposite for the default implementation of JPA. As mentioned above, The JPA do a default mapping for the properties and instance variables that are located into a persistent class with their columns by using the uppercase of the properties’ name. While the Transient annotation has used with those properties and instance variables that the JPA ordered to ignore them.
Look at the Employee class, if you’ve added a property that haven’t an identical column at the database, you are almost probably getting an exception says:
Unknown column 'EMPLOYEESALARY' in 'field list'
Even of your code doesn’t display an error at compile time, but it surely will throw a runtime exception if you have tried doing a query for your employees. That exception will tell us about missing column.
package net.javabeat.eclipselink.data; import javax.persistence.Basic; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.Id; @Entity public class Employee { @Id private int employeeId; @Basic(optional=false) private String employeeName; private String employeeSalary; // failure possibility public int getEmployeeId() { return employeeId; } public void setEmployeeId(int employeeId) { this.employeeId = employeeId; } public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public String getEmployeeSalary(){ return this.employeeSalary; } public void setEmployeeSalary(String employeeSalary){ this.employeeSalary = employeeSalary; } public String toString(){ return this.employeeId+" "+this.employeeName; } }
To avoid such that exception, the properties being ignored could be marked as @Transient. The implementation of JPA will discard them.
@Transient private String employeeSalary;