JAKARTA EE FOR JUNIOR DEVELOPERS - Lesson 3 Entity Class (Part 1)

 

INTRODUCTION

In this Jakarta EE for Junior Developers lesson, we will start analyzing the one of the Jakarta EE specifications which is the Jakarta Persistence.
As the first step, we will look at how to create the necessary files that a project needs in order to properly communicate with a database. As the second step, we will familiarize ourselves with the Jakarta EE Persistence specification, and then we will create our first table in the database by defining its name and columns. 

WHAT IS ORM?

An ORM (Object-Relational Mapping) framework, such as Jakarta Persistence, is used to simplify the interaction between object-oriented programming languages (like Python, Java, or C#) and relational databases (such as MySQL, PostgreSQL, or SQLite). The primary purpose of an ORM is to automate the process of translating data between these two paradigms. In simple terms, an ORM framework takes full responsibility to correctly translate java code to database tables and vice versa. ORMs abstract the database interaction, meaning you don't have to manually write SQL queries for every database operation. This makes the code cleaner and easier to maintain. Jakarta Persistence defines a standard for management of persistence and object/relational mapping in Java environments.

WHY WE NEED AN APPLICATION SERVER?

An application server (such as Wildfly, Payara, Tomcat, etc) is essential for managing and running web applications and services in a structured and efficient way. Among other features, that we will explore in future lessons, an application server manages transactions (such as ACID compliance), and making sure that database transactions are handled correctly across different components of the application. It also provides built-in support for enterprise-level services, such as messaging, database access (JDBC, JPA), security (authentication, authorization), and web services (REST, SOAP). This reduces the need to reinvent these features from scratch. In the context of the Jakarta Persistence, the Application server (Wildfly in our case) provides the container within operates as a bridge between the deployed application and the database.


CREATING A WEB PROJECT

The first step, as we have already mentioned, is to create a Web Project. This process is quite easy within the NetBeans environment.

Click on File and then New Project.



Make sure that you select "Java with Maven" under the Categories column, whereas under Projects you select "Web Application".



On the "Name and Location" step type the name of the Project and as well as the name of the first package that will be created.


This step is the most important because now we have the option to choose the Application Server and the Jakarta EE version that we want to use to build our application. The name of the Application Server will appear on the drop-down list only if we have already registered it with NetBeans as we have done already on Lesson 2. We choose to develop our applications using the latest stable version of Jakarta EE 10 Web Profile. Click the Finish button to complete the Jakarta EE 10 Web application creation process.



After few seconds, the new project will appear on the projects list. Before we explore its structure, let's run it and see what we have accomplished so far.

Right click on the project name and select the Run option. 


That action will result in two steps - Wildfly will start and then the project will be deployed and run. On the default browser a simple message will appear.



In addition to what you see on your browser, we can actually verify the deployment of our project by looking at the deployed application at the Wildfly.



PROJECT STRUCTURE

The project combines two features - a Web site and a REST Web Service. The simple web page that you just saw on your browser is coming from the Web Pages folder.


Inside the Source Packages we can find the classes needed to create a simple Web Service. We can get verify the functionality of the web service if we just right click on the name of the service under the HTTP Methods folder and click on the Test Resource Uri.




It is too early to discuss more details about RESTful Web Services. For now we just leave all these classes as it is and we will come back to them later in our series. 

So far, we have understood that we have created a very basic but functional Jakarta EE Web Application. However, there are couple more files that we need to explore before we are in position to create tables on our database.

The first one is the pom.xml file that is located under the Project Files folder. Double click on it to open it.


The first thing you notice under the dependencies section is the fact we do not have to manually provide any libraries because they are all provided by the Application server. Wildfly has the entire Jakarta EE framework loaded for us, so we do not have to add anything extra. 


As we are still inside the pom.xml file, we have to make sure that we changed the source and target version of java to the one that we have installed on our computer. In my case, that will be JDK 21. 


When we complete any changes on the pom.xml file or on the java classes, we need to rebuild the project. All we have to do is to right click on the project and select "Clean and Build".


If the output from the build process is success when we can execute the run command again from the drop down menu as we did before.


PERSISTENCE UNIT

So far we have configured, the database, the Wildfly application server and we are just about ready to start creating our first class that will be converted to a database table when the application is deployed. However, there is a gap in this chain of logic. How can we actually call the Wildfly database configuration that we have completed previously to save or retrieve data from the database? How does our app knows in what database the information will be written to? All these questions are answered by the persistence unit that you can find in the Jakarta EE Persistence specification (Jakarta Persistence).


The persistence unit is defined in the persistence.xml file, which is typically located in the META-INF directory of the application's classpath. Our application already contains an empty persistence.xml file under the Other Sources folder.


When we double click on the persistence.xml file, a graphical interface windows opens in the center of NetBeans that allows us to easily configure the basic options.


To understand the purpose of each of these options we just have to refer back to the Jakarta EE Persistence specification. 

Persistence Unit Name: (Section 8.2.1.1) The name attribute defines the name for the persistence unit.

Persistence Provider: (Section 8.2.1.4) The provider element specifies the name of the persistence provider’s jakarta.persistence.spi.PersistenceProvider class. The provider element is optional, but should be specified if the application is dependent upon a particular persistence provider being used. EclipseLink is an open-source persistence provider for the Jakarta Persistence API (JPA), and it's one of the most widely used JPA implementations. It is a reference implementation of JPA and serves as a bridge between Java objects and relational databases by providing advanced mapping capabilities. So, in simple terms, the persistence unit offers the connection and EclipseLink does the translation from java objects to sql queries.

Data Source: (Section 8.2.1.5) In Jakarta EE environments, the jta-data-source and non-jta-data-source elements are used to specify the JNDI name of the JTA and/or non-JTA data source to be used by the persistence provider. The name we have selected is the conncetion that we had setup and that is the connection that the persistence unit will call to execute CRUD operations (Create, Read, Update, Delete) on the database.


Use Java Transaction APIs: (Section 8.2.1.2) The transaction-type attribute is used to specify whether the entity managers provided by the entity manager factory for the persistence unit must be JTA entity managers or resource-local entity managers. The value of this element is JTA or RESOURCE_LOCAL. A transaction-type of JTA assumes that a JTA data source will be provided—either as specified by the jta-data-source element or provided by the container. In general, in Jakarta EE environments, a transaction-type of RESOURCE_LOCAL assumes that a non-JTA datasource will be provided. In a Jakarta EE environment, if this element is not specified, the default is JTA. In a Java SE environment, if this element is not specified, the default is RESOURCE_LOCAL.

Table Generation Strategy: (Section 9.4) In cases where a preconfigured database (or a “legacy” database) is not used or is not available, the Jakarta Persistence schema generation facility may be used to generate the tables and other database artifacts required by the persistence application. The jakarta.persistence.schema-generation.database.action property specifies the action to be taken by the persistence provider with regard to the database artifacts. The values for this property are "none""create""drop-and-create""drop". If the jakarta.persistence.schema-generation.database.action property is not specified, no schema generation actions must be taken on the database. The create-drop option will create the schema when the application starts and drop the schema when the application stops. This is often used in testing environments where the schema should be recreated and removed automatically.

Validation Strategy: (Section 3.6.1.1) The validation-mode element of the persistence.xml file determines whether the automatic lifecycle event validation is in effect. The values of the validation-mode element are AUTOCALLBACKNONE. The default validation mode is AUTO. It controls when validation should occur in relation to the persistence operations (such as when saving, updating, or removing entities from the database). 

Shared Cache Mode: (Section 8.2.1.7) The shared-cache-mode element determines whether second-level caching is in effect for the persistence unit. If either the shared-cache-mode element is not specified in the persistence.xml file or the value of the shared-cache-mode element is UNSPECIFIED, and the jakarta.persistence.sharedCache.mode property is not specified, the behavior is not defined, and provider-specific defaults may apply.

Include All Entity Classes: (Section 8.1) The set of managed classes included in the persistence unit and managed by the entity managers of the entity manager factory.

The explanation of the terms might be a bit long, but the actual configuration is pretty easy as you have already noticed. Now, you can actually see the final configuration file if you click on the Source button of the persistence window.


There is a small bug in the creation of the persistence unit within the NetBeans environment. The name of the framework is still shown as javax and not jakarta. Make sure that you type jakarta in the place of javax. The rest of the configuration remains the same. Here is my complete persistence unit.

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="3.0"
             xmlns="https://jakarta.ee/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence                            
             https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd">
  <!-- Define Persistence Unit -->
  <persistence-unit name="my_persistence_unit" transaction-type="JTA">
    <jta-data-source>java:/PostgresDS</jta-data-source>
    <validation-mode>AUTO</validation-mode>
    <properties>
      <property name="jakarta.persistence.schema-generation.database.action" value="drop-and-create"/>
    </properties>
  </persistence-unit>
</persistence>


THE ENTITY CLASS

An entity class in Java is a class that represents a database entity and is used with JPA to interact with a relational database. We can take any regular Java class and by adding some special annotations it will be transformed into an entity.

Section 2.1 from the Jakarta Persistence specification lists few simply rules that we need to follow in order to properly create an entity class.
  • The entity class must be annotated with the Entity annotation.
  • The entity class must have a no-arg constructor.
  • The entity class must be a top-level class.
  • The entity class must not be final.
  • Must implement the Serializable interface.
  • Persistent instance variables must be declared private, protected, or package-private.
Before we create our first entity class, let's first create a package. Right click on the Source Packages and then click on New and finally on the option Java Package.


Name the package com.mycompany.jakartaee.entities and press Finish.


Now that our package is created, we right click on the package and this time we select the option to create an Entity class.


We assign the name Employee to this class and we click on Finish. Notice the option Primary Key Type which the data type Long is automatically assigned. We will explain that option shortly. Let's complete the process for now.


What we have really accomplished is the fact that we use a NetBeans template to create an entity class that follows all the rules mentioned on the specification. So we do not have to remember them.

Employee.java

package com.mycompany.jakartaee.entities;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import java.io.Serializable;

@Entity
public class Employee implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Employee)) {
            return false;
        }
        Employee other = (Employee) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "com.mycompany.jakartaee.entities.Employee[ id=" + id + " ]";
    }
   
}

@Entity (Section 2.1)
This annotation tells JPA that this class should be mapped to a table in a relational database. By default, the table name will be the same as the class name.

@Id (Section 2.4)
The id field is annotated with @Id, indicating that it is the primary key for the Employee entity. Each Employee object will be uniquely identified by the value of the id field in the database.

@GeneratedValue(strategy = GenerationType.AUTO) (Section 11.1.20)
The @GeneratedValue annotation in Java is used in combination with the @Id annotation to specify how the value of the primary key field should be generated. It tells the Java Persistence API (JPA) to automatically assign a value to the primary key, typically in a way that ensures it is unique for each entity. When you use @GeneratedValue(strategy = GenerationType.AUTO), you're telling JPA to let the persistence provider (EclipseLink) decide the best strategy for generating primary key values based on the underlying database.

Right click on the project and execute the command Clean and Build. You need to execute this command every time you add new code to your project.

 

Now you are ready to Run the project. 


When the message shows on your browser, return back to NetBeans and refresh the JakartaEEDB.


After expanding the Tables folder, you should be able to see the Employee table that contains one column with the name id.


Congratulations! We now have our first entity created. On the next Jakarta EE for Junior Developers lesson, we will add more columns on the table, as well as we will explore more annotations.



full-width

Post a Comment

0 Comments