End-to-End JPA Collections with MySQL, Part 1
- Entity and Value Types / A Simple Person Entity
- Creating Departments and Adding Person Entities / Named Queries
- Setting Up Your Own JPA Eclipse Project / Importing the Downloaded JPA Eclipse Project / Setting Up the MySQL Database
- Checking the Contents of the Database / Explaining the Relationship Between the Entities
- Setting Up the Persistence Unit / Running the Code / Conclusion
End-to-End JPA Collections with MySQL, Part 1
It's all about data nowadays and for good reason. In an increasingly online world, the value of data is massive, and it's plain to see how organizations walk a tightrope when it comes to data. Why the tightrope? Well, it's because big data is big money, and getting access to data may involve some degree of privacy violation.
Aside from the business issues, at the heart of the matter there is one dominant technology: relational databases. The information that resides in databases can now be counted on to far outlive the applications used to create it. So, a solid knowledge of the database area is a good investment for programmers who are keen to move up the value chain.
In this two-part article series, I'll be demonstrating how to create a collection-based JPA model and how to implement this using MySQL. In Part 2, I'll look at an increasingly important server-side technology: stored procedures. To get started, let's have a quick look at the difference between entity and value types. It might be useful to refer to my earlier articles on JPA and Hibernate.
Entity and Value Types
In Hibernate, types can be either entity or value. An entity type has a persistent identity, which means it has an independent database life cycle. In other words, entities can be persisted to the database, read from the database, updated, etc. A value type differs from an entity type because it doesn’t have a persistent identity. However, entity and value types often tend to go hand in hand.
A typical entity type is a usere.g., a system user. The postal address of such a user can be modeled as a value type. It may therefore help to think of a value type as an attribute of an entity. It's no surprise then to realize that an entity may support individual value types as well as collections of value types. A collection of entity types is also possible. Before looking at a collection example, let's review the basic entities in the model under consideration: Person and Department. A department contains zero, one, or more persons (or people).
A Simple Person Entity
This leads into our first code example in Listing 1.
The first entity we’ll look at in Listing 1 is a Person entity class.
Listing 1A Person Entity
@Entity @Table(name = "PERSON") public class Person implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name = "PERSON_ID") private Long id; private String lastName; private String firstName; private String friends; public Person() { } public Long getId() { return id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getFriends() { return friends; } public void setFriends(String friends) { this.friends = friends; } @Override public String toString() { return "Person [id=" + id + ", lastName=" + lastName + ", firstName=" + firstName + ", friends=" + friends + "]"; } }
In Listing 1, you see a simple mapping of a Person class as indicated by the @Entity annotation. This annotation describes the class as a persistent entityi.e., an instance of this class will typically reside in a row in the database. The rest of the Person class is just getter and setter methods and a toString() method.
In Listing 2, you see a Department classa somewhat more complex item than the Person class in Listing 1.
Listing 2A Department Entity Type with a Collection of Person Entities
@Entity @Table(name = "DEPARTMENT") public class Department implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name = "DEPT_ID") private Long id; @Column(name = "name", unique=true) private String name; private List<Person> persons = new ArrayList<Person>(); public Department() { } public Department(String name) { this.name = name; } public Long getId() { return id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @OneToMany(cascade=CascadeType.ALL, mappedBy="department") public List<Person> getPersons() { return persons; } public void setPersons(List<Person> persons) { this.persons = persons; } @Override public String toString() { return "Department [id=" + id + ", name=" + name + "]"; } }
In Listing 2, an important item is illustrated in the following line:
private List<Person> persons = new ArrayList<Person>();
This line indicates that the Department class contains a collection of Person instances. In fact, Listings 1 and 2 provide an example of what's called a unidirectional one-to-many association. This simply means that one department can contain zero, one, or more persons. The unidirectional aspect of the relationship reflects the fact that Department entities know about the Person instances contained within them, but not vice versa.
Let's see how to use these classes in some simple Java code, as illustrated in Listing 3.
Listing 3Creating a Department Entity
public void createDepartment(String departmentName) { try { // Start EntityManagerFactory EntityManagerFactory emf = Persistence .createEntityManagerFactory("punit"); // First unit of work EntityManager entityManager = emf.createEntityManager(); EntityTransaction entityTransaction = entityManager .getTransaction(); entityTransaction.begin(); Department department = new Department(departmentName); entityManager.persist(department); entityTransaction.commit(); entityManager.close(); emf.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
Don't worry about the details in Listing 3 for the moment. You'll see the whole picture shortly when we look at a full Eclipse project. In Listing 3, I pass in a department name as a Java String, and I then create an instance of the Department class with the following lines:
Department department = new Department(departmentName); entityManager.persist(department);
The code in Listing 3 all boils down to creating an instance of Department by calling entityManager.persist(). This is the magic of object relational mapping.
The code that encloses the previous two lines is required if you run the project outside of a containere.g., if the code is run in a JavaSE environment. If, on the other hand, you use one of the usual containerssuch as, JBoss or Glassfish or WebLogicthen the previous two lines are typically all that is required. In the case where a container such as JBoss is used, then the EntityManager instance is typically injected into the code, thereby simplifying the Listing 3 method. The injection mechanism is referred to as dependency injection, and one of its merits is that the container helps you to simplify your code. The downside to dependency injection is that it imposes a configuration burden, but there's no such thing as free technology!
You've now seen how to persist an instance of Department. What about creating a Person instance in the database? Well, it's a similar story to Listing 3 as illustrated in Listing 4.
Listing 4Creating a Person Entity
public void createPerson(Person person) { try { // Start EntityManagerFactory EntityManagerFactory emf = Persistence .createEntityManagerFactory("punit"); // First unit of work EntityManager entityManager = emf.createEntityManager(); EntityTransaction entityTransaction = entityManager .getTransaction(); entityTransaction.begin(); entityManager.persist(person); entityTransaction.commit(); entityManager.close(); emf.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
In Listing 4, I pass in a Person instance, which simplifies the persistence code down to the same boilerplate code as in Listing 3 but with this line added:
entityManager.persist(person);
Again, if we run the code in a container, then it becomes much simplified!