As mentioned earlier, Spring Data JPA is an abstraction layer that allows us to interact with objects in your code rather than write SQL queries.
These objects, in this context, are referred to as models (or entities). Typically, we write Java classes and use annotations to identify them as models to Spring Data JPA. Then, Spring Data JPA sends instructions to the Hibernate ORM to execute the correct SQL statements depending on the methods that we’ve called on our model and the annotations we’ve put on its fields.
You can imagine that a model corresponds to a database table, and a field in a model corresponds to a column in that table. An application developer will use annotations to indicate how the model name and field names translate to the underlying table name and column names, respectively. To gain a better understanding of how we can create a model, and use annotations to map it to the underlying database relation/table, let’s analyze an example.
Below, you’ll see a Plain Old Java Object (a POJO) that represents a person, storing their attributes as fields of our POJO.
// Person, a Plain Old Java Object (POJO), that we use to represent a person. public class Person { // An ID to uniquely identify the person we are storing in our db private Integer id; private String name; private Integer age; private String eyeColor; }
Now that we have a baseline representation of what a Person
is and what we wish to store about them, we can add annotations from JPA that help define how our Java object will map to a database relation.
import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Column; import javax.persistence.Table; @Entity @Table(name="PEOPLE") public class Person { @Id @GeneratedValue private Integer id; @Column(name="NAME") private String name; @Column(name="AGE") private Integer age; @Column(name="EYE_COLOR") private String eyeColor; }
In the example, we start with importing all of the annotations that we’ll need. These annotations come from the JPA library, which comes along with the spring-boot-starter-data-jpa
dependency.
Then, we add in all the required annotations that define the translation between our POJO and our database relation:
@Entity
: tells the ORM that this model will be used to represent a table or relation in our database@Table
: tells the ORM what table name in the underlying database that this model corresponds to. Here, it is used to say that thePerson
entity represents a single entry in the"PEOPLE"
table of the underlying database.@Id
: tells the ORM that this field (id
) will be used to uniquely identify a single entry in our"PEOPLE"
relation@GeneratedValue
: tells the ORM that the developer will not be supplying the value for this field themselves. Instead, it should be “auto-generated” by the database. Typically, an@Id
field for an entity will be auto-generated in this way, so that we can leverage the database to guarantee that the ID will always be unique.@Column
: tells the ORM what column in the underlying relation that the annotated field corresponds to. For example, theeyeColor
field of our entity corresponds to the"EYE_COLOR"
column in the"PEOPLE"
relation.
There are many more annotations that JPA provides to help define more complex relationships between a model and its underlying relation in the database. You can read more about them here under the Annotation Types Summary heading. However, the ones from the example above should cover the majority of common use cases.
When the ORM interacts with your model, it depends on “getter” and “setter” methods that have been appropriately named based on the fields. For the Person
class, we would additionally need to add getter and setter methods for every field to ensure that the ORM can access and modify fields in the model as required.
We won’t write out the whole class again, but you can imagine that the age
field, for example, would have a getter and setter like this:
@Column(name="AGE") private Integer age; public Integer getAge() { return this.age; } public void setAge(Integer age) { this.age = age; }
Now that you are equipped to define models and use JPA annotations to map them to relations, you can apply these skills for the plant management application we are creating for the botanist!
Instructions
You’ll start by defining a POJO to represent our plant. Take a look at Plant.java in the entities folder.
Next, define a public class Plant
, that has the following private
fields:
- an
Integer
that will represent the plant’sid
- a
String
to store the plant’sname
- an
Integer
to store the plant’squantity
- an
Integer
to store the plant’swateringFrequency
, in days - a
Boolean
to store whether or not the planthasFruit
Now that you have the baseline model defined, you’ll have to add annotations that tell JPA how to map your model to the underlying database relation.
Add the annotation to your model that tells JPA that this model will be used to represent a database relation, as well as the annotation that indicates which specific table it maps to.
The table behind your Plant
model should have its name
as "PLANTS"
.
Make sure you import
the required annotations first, from the javax.persistence
package.
Add the annotations to specify that the id
field:
- Should be used as the unique identifier for a
Plant
- Should be generated automatically
Like the annotations from the previous step, these annotations should also be imported from the javax.persistence
package.
Add the annotations to map each field to the appropriate underlying table column:
- The
name
field should be mapped to the"NAME"
column - The
quantity
field should be mapped to the"QUANTITY"
column - The
wateringFrequency
field should be mapped to the"WATERING_FREQUENCY"
column - The
hasFruit
field should be mapped to the"HAS_FRUIT"
column
Remember to import the annotation from the javax.persistence
package!
Remember, the ORM (object-relational mapping) will not be able to interact with your model without getters and setters!
For each field in the Plant
model, make sure you add an appropriately named getter
and setter
method.