HelloWorld JPA application

Welcome to our JPA hello world tutorial, where we’ll guide you through the basics of Java Persistence API (JPA).  Follow along as we demonstrate step-by-step instructions, best practices, and practical examples to ensure you grasp the fundamental concepts of JPA programming. Let’s dive into this comprehensive tutorial and unlock the power of JPA for your next project.

Create the Maven project

Firstly, we need a Maven project for our HelloWorld JPA application. We recommend using the Jakarta EE Starter which allows to generate a Maven project for Jakarta EE 8/9/10 Projects: https://start.jakarta.ee/

Select the Jakarta EE version, the Java version and the Runtime, for example WildFly application Server:

jpa hello world tutorial

Coding the Entity Class

Firstly, let’s define our Model. We will be using a single Customer Class to map a Database Table.

jpa example wildfly

Here is our Customer Class definition:

@Entity
public class Customer implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private String email;
    private String address;

    @Column(name = "phone_number")
    private String phoneNumber;

    // Getter/Setter methods omitted for brevity
}

To learn more about different types of Strategies you can use for Primary Keys check this article: Choosing the Strategy for Primary keys in JPA

Coding the Service Class

Next, in order to store our Entity in a transactional way, we a CDI Bean which uses Transactional methods in insert and update operations:

@Model
public class CustomerService {
    private static final Logger LOGGER = Logger.getLogger(CustomerService.class.getName());

    @PersistenceContext
    EntityManager em;

    @Transactional
    public void createCustomer(Customer customer) {
        em.persist(customer);
        LOGGER.info("Created Customer "+customer);

    }


    @Transactional
    public void updateCustomer( Customer customer ) {
        Customer customerToUpdate = findCustomerById(customer.getId());
        customerToUpdate.setName(customer.getName());
        customerToUpdate.setEmail(customer.getEmail());
        customerToUpdate.setAddress(customer.getAddress());
        customerToUpdate.setPhoneNumber(customer.getPhoneNumber());

        LOGGER.info("Updated customer" + customer);
    }


    @Transactional
    public void deleteCustomer(Long customerId) {
        Customer c = findCustomerById(customerId);
        em.remove(c);
        LOGGER.info("Deleted Customer with id" + customerId);
    }


    public Customer findCustomerById(Long id) {
        Customer customer = em.find(Customer.class, id);
        if (customer == null) {
            throw new WebApplicationException("Customer with id of " + id + " does not exist.", 404);
        }
        return customer;
    }


    public List<Customer> findAllCustomers() {
        Query query = em.createQuery("SELECT c FROM Customer c");
        List<Customer> customerList = query.getResultList();
        return customerList;
    }



    public Customer findCustomerByName(String name) {
        Query query = em
                .createQuery("SELECT c FROM Customer c WHERE c.name = :name");
        query.setParameter("name", name);
        Customer customer = (Customer) query.getSingleResult();
        return customer;
    }

}

Coding a REST Endpoint for the Service Class

Finally, we need a front-end for our application. To keep it pretty simple, we will add a basic REST Endpoint which maps all the Service methods:

@Path("/customer")
@Produces("application/json")
@Consumes("application/json")

public class CustomerEndpoint {

    @Inject
    CustomerService customerService;

    @POST
    public Response create(Customer customer) {
        customerService.createCustomer(customer);
        return Response.status(201).build();
    }

    @GET
    public List<Customer> findAllCustomers() {
        return customerService.findAllCustomers();
    }

    @GET
    @Path("/{id}")
    public Customer findCustomerById(@PathParam("id") Long id) {
        return customerService.findCustomerById(id);
    }

    @PUT
    public Response updateCustomer(Customer customer) {
        customerService.updateCustomer(customer);
        return Response.status(204).build();
    }
    @DELETE
    @Path("/{id}")
    public Response delete(@PathParam("id") Long id) {
        customerService.deleteCustomer(id);
        return Response.status(204).build();
    }

}

As you can see, the above REST endpoint has some basic methods for creating and querying our Entity objects, returning a JSON view of it. In order to get it working our REST Services, we need a REST Activator class:

@ApplicationPath("/rest")
public class RestActivator extends Application {
	
}

Adding the persistence.xml file

Then, we will add a persistence.xml file which binds the Persistence Unit to the default ExampleDS Datasource that is available in WIldFly.

<persistence 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_1.xsd"
             version="3.1">
    <persistence-unit name="primary">
        <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
        <properties>

            <!-- AUTO-GENERATED FROM ANNOTATIONS METADATA -->
            <property name="jakarta.persistence.schema-generation.database.action"
                      value="drop-and-create"/>
            <property name="jakarta.persistence.schema-generation.create-source"
                      value="metadata"/>
            <property name="jakarta.persistence.schema-generation.drop-source"
                      value="metadata"/>

            <property name="hibernate.show_sql" value="true"/>

        </properties>
    </persistence-unit>
</persistence>

As you can see from the above configuration, we are also adding the properties to allow the generation of the Database schema from the annotations available in the application.

Some sample Data with import.sql

Finally, we will add a resources/import.sql file to insert some sample data at start:

INSERT INTO Customer (name, email, address, phone_number) VALUES ('John Doe', '[email protected]', '123 Main Street', '555-1234')
INSERT INTO Customer (name, email, address, phone_number) VALUES ('Jane Smith', '[email protected]','45 Elm Street','34243')

Run and Test the Project

Now compile the project:

$ mvn clean install wildfly:deploy

Then, let’s list all available Customers:

curl -s -X GET http://localhost:8080/jpa-basic/rest/customer | jq
[
  {
    "address": "123 Main Street",
    "email": "[email protected]",
    "id": 1,
    "name": "John Doe",
    "phoneNumber": "555-1234"
  },
  {
    "address": "45 Elm Street",
    "email": "[email protected]",
    "id": 2,
    "name": "Jane Smith",
    "phoneNumber": "34243"
  }
]

To add a new Customer:

curl -X POST -H "Content-Type: application/json" -d '{
  "name": "Frank Smith",
  "email": "[email protected]",
  "address": "123 Random Street",
  "phoneNumber": "432-1234"
}' http://localhost:8080/jpa-basic/rest/customer

To update an existing Customer:

curl -X PUT -H "Content-Type: application/json" -d '{
  "id": {id},
  "name": "Updated Name",
  "email": "[email protected]",
  "address": "456 Elm Street",
  "phoneNumber": "555-5678"
}' http://localhost:8080/jpa-basic/rest/customer

Finally, to delete a Customer:

curl -X DELETE http://localhost:8080/jpa-basic/rest/customer/{id}

Conclusion

Congratulations on completing this JPA hello world tutorial! You have gained a solid understanding of Java Persistence API and its capabilities for simplifying database operations and improving code maintainability. By following along with our step-by-step instructions and practical examples, you have taken the first step towards becoming proficient in JPA programming. Armed with this knowledge, you can now confidently incorporate JPA into your projects, unlocking its power to streamline data persistence and manipulation. Keep exploring and experimenting with JPA’s advanced features to take your data management to the next level. Happy coding with JPA!

You can find the source code for this JPA application on: https://github.com/fmarchioni/mastertheboss/tree/master/javaee/jpa-basic

Found the article helpful? if so please follow us on Socials