- Converging Software
- JPA Shopping List
- What Is an Entity?
- Main Program
- Populating the Database
- Conclusion
What Is an Entity?
The best way to think of an entity is as something that can be described as a noun in your problem domain; for example, Customer, User, System, Network, and so on. Entities are the low-level atoms that represent your problem domain. You model these atoms as entities. Listing 1 shows a complete entity class called Message.java. For the moment, ignore the lines that start with the "at" (@) symbol; those are called annotations, and I'll discuss them shortly.
Listing 1 An entity class.
import javax.persistence.*; @Entity @Table(name = "MESSAGES") public class Message { @Id @GeneratedValue @Column(name = "MESSAGE_ID") private Long id; @Column(name = "MESSAGE_TEXT") private String text; @ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "NEXT_MESSAGE_ID") private Message nextMessage; Message() {} public Message(String text) { this.text = text; } public Long getId() { return id; } private void setId(Long id) { this.id = id; } public String getText() { return text; } public void setText(String text) { this.text = text; } public Message getNextMessage() { return nextMessage; } public void setNextMessage(Message nextMessage) { this.nextMessage = nextMessage; } }
Putting aside the annotations for the moment, Listing 1 is just a normal Java class. In fact, the expression used to describe such a class is "Plain Old Java" class, or POJO for short. The POJO in Listing 1 contains three data members (fields), as shown in Listing 2.
Listing 2 The POJO fields from Listing 1.
private Long id; private String text; private Message nextMessage;
Looking at the rest of Listing 1, the code is simply made up of two constructors and getter and setter methods for the fields in Listing 2. Now let's examine the annotations.
Getting into Annotations
For the most part, annotations are fairly obvious, and an intelligent guess will generally uncover their purpose in the code. In Listing 1, the annotations start off this way:
@Entity @Table(name = "MESSAGES") public class Message
The @Entity annotation identifies the class as being persistent. This is an indication to the entity manager that instances of this class will be written to a database. In other words, each new instance of the class will become a row in a relational database table. But what table will be used to store the instances of Message? To answer this question, look at the second annotation:
@Table(name = "MESSAGES")
As I said, it's generally possible to guess the function of the annotation. This is because annotations are supposed to be relatively self-documenting. In this case, you might correctly guess that instances of the Message class will be stored in a table called MESSAGES. So far, so good—nothing too difficult. Now what about the class code? The next annotations are inside the Message class and look like this:
@Id @GeneratedValue @Column(name = "MESSAGE_ID") private Long id;
To understand these annotations, we must take a small detour into database land and consider the issue of table keys.
One of the principal requirements of using databases is uniqueness of table rows. This requirement isn't hard to understand: If you reserve a hotel room, you want your reservation to be unique in the database. This simply means that you (and only you) have a reservation on a given room. Uniqueness can be solved by the use of a key value. Keys can be simple integers, and their only stipulation is that any given key cannot be repeated in any other rows in the table.
Returning to the example of a hotel room reservation, the key can be an integer value, and in the annotation above this is exactly the case. Our annotation uses a private Long member to model the key value. Looking at the complete annotation, you might now be able to guess its overall function:
@Id @GeneratedValue @Column(name = "MESSAGE_ID") private Long id;
The @Id annotation indicates that the field following the annotation is an identity or key value. Such values uniquely differentiate the rows in the table, but which column is referenced? The @Column annotation indicates that the key column is to be called MESSAGE_ID.
Let's recap. Our database table is called MESSAGES and it contains a key column called MESSAGE_ID. To complete the picture, let's look at how to map a non-key table column using the following annotation:
@Column(name = "MESSAGE_TEXT") private String text;
Again, if you apply a logical approach to the annotations you can usually guess what's going on. In this case, we have a new column called MESSAGE_TEXT. This column is also added to the table MESSAGES.
The process of writing a POJO with annotations is often referred to as mapping. In fact, I've often used this term in my consultancy work to describe the process to clients. Most managers can understand your Java coding, and the same is true for SQL coding. JPA work is more difficult for a non-technical person to understand, so a generic term like "mapping" is very useful. In effect, you're mapping between two domains: Java and relational databases. When we run the code you'll see how the mapping works, but for the moment just note that we're bridging two very different technologies—the old and the new!
Returning to the POJO, the next annotation is a little more complex.
@ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "NEXT_MESSAGE_ID") private Message nextMessage;
Starting at the bottom of this code section, each instance of the Message class contains an instance of Message. Remember that the database contains a row for each instance of Message. The annotation above indicates a relationship between the rows in this table; in this case, the relationship is many-to-one. In other words, one entity has a relationship with many entities. How are these entities related? The relationship is modeled using a column in the table, more specifically one with the @JoinColumn annotation. The latter specifies a column name that forms the basis for the relationship.
The cascade simply relates to the way changes to the owning entity are propagated through the relationship hierarchy.
Other Details of the Entity Class
The remainder of the entity class can be summed up as follows:
- Default constructor
- Non-default constructor
- Methods to set data members
- Methods to get data members
The default constructor is mandatory for persistent classes. The non-default constructor is used to pre-populate an instance of the entity class. The getters and setters are merely used to retrieve and modify the data members. Now, how do we instantiate the entity class? Simple—we use another class.