|

5 Things Beginners Need to Know Before Using JPA / Hibernate / EclipseLink


Take your skills to the next level!

The Persistence Hub is the place to be for every Java developer. It gives you access to all my premium video courses, monthly Java Persistence News, monthly coding problems, and regular expert sessions.


A solid understanding of JPA and its implementations is still one of the most in-demand skills among Java developers. So, it’s no surprise that there are several blog posts, books, and courses available that teach you how to implement a persistence layer using the JPA specification. I even recorded a JPA for Beginners course myself.

But if you’ve never used JPA before and think about investing your time and money to learn about it, you’re probably wondering what you need to know about JPA and why it’s used that often. So, let’s take a look at the 5 most important things you need to know about JPA.

1. JPA maps almost everything

Let’s start with the most obvious: The JPA specification defines an object-relational mapping between tables in a relational database and a set of Java classes.

The great thing about it is that JPA makes this mapping very easy. Quite often, you only need to annotate your class with an @Entity annotation. All its attributes then get automatically mapped to database columns with the same name. Here you can see an example of such a basic mapping.

@Entity
public class Professor {

	@Id
	private Long id;
	
	private String firstName;
	
	private String lastName;

	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 void setId(Long id) {
		this.id = id;
	}
	
	public Long getId() {
		return id;
	}
}

If you want to learn about JPA’s basic entity mappings, please watch this sample lecture of my JPA for Beginners course.

And you can not only map basic attributes to database columns, but you can also model associations between your entities. This enables you to represent the foreign key columns and association tables of your table model as entity attributes with getter and setter methods. You can use these attributes in the same way as you use any other entity attribute. Your JPA implementation makes sure to fetch the required records either during the initialization of your entity or when you use them for the first time.

You can see the mapping of a typical many-to-one association between the Professor and the Course table in the following code snippet. The Professor professor attribute models the association, and the JPA implementation makes sure to perform the required read and write operations.

@Entity
public class Course {

	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "course_generator")
	@SequenceGenerator(name = "course_generator", sequenceName = "course_seq")
	private Long id;

	private String name;

	private LocalDate startDate;

	private LocalDate endDate;

	@ManyToOne
	private Professor professor;

	...
}

2. JPA is a specification that requires an implementation

This is probably one of the confusing things if you’ve never worked with JPA or any other Jakarta EE specification.

JPA is only a specification which defines a set of interfaces and their functionality. That means that you can use the specification to implement your application, but you can’t execute it without adding an implementation. Two well-known JPA implementations are EclipseLink, which is the reference implementation, and Hibernate, which is the most popular JPA implementation.

3. JPA introduces abstraction and indirection

I explained at the beginning of this article that JPA maps your Java classes to database tables and that this even includes associations between these classes. This mapping obviously introduces an abstraction. The level of abstraction between a simple attribute and a database column might be rather small, but it’s much higher for association mappings. Your persistence provider then not only has to provide the type conversion between the JDBC type of your database column and the Java type of your entity attribute, but it also needs to manage additional queries to retrieve the related records.

This makes it extremely important that you understand the mapping and its implications. Otherwise, your JPA implementation will handle these relationships inefficiently, and your application will suffer from severe performance problems. That’s why I’m spending 4 lectures of my JPA for Beginners Online Training on the different association mappings and their fetching behavior.

In addition to the abstraction introduced by the attribute mappings, JPA also triggers the required insert, update and remove operations based on a complex lifecycle model. The good thing about it is that you no longer need to write any SQL statements to persist, update or remove a database record. But at the same time, you’re losing control over the statement and when it gets executed.

The automatic creation and execution of SQL statements make it very easy to implement your business logic and improves your productivity. But it also makes it hard to predict when your JPA implementation executes which SQL statements. You, therefore, need a solid understanding of the JPA’s lifecycle model and how it affects the execution of SQL statements. That’s why I included a detailed lecture about it in my beginners training.

4. You still need to understand relation table models

JPA abstracts the database access and hides it behind a set of annotations and interfaces. But that doesn’t mean that you can ignore your database. Even so, you don’t interact directly with your table model; you still need to understand the capabilities and limitations of relation table models. Ignoring them is one of the most common mistakes that cause severe performance problems.

You should, therefore, make sure that your entities are as similar as possible to the database table they map. This ensures that your persistence provider can provide you a fast and efficient object-relational mapping.

5. You still need to know SQL

Another thing you can’t ignore if you’re using JPA is that your database still executes SQL statements. By using JPA, you don’t have to write these statements yourself. But you still should be able to read and understand them. That enables you to understand how your persistence provider interacts with the database and to implement efficient database operations.

But before you can see the executed SQL statements, you need to configure your persistence provider so that it logs them. You can see the required configuration for Hibernate in the following code snippet.

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%c] - %m%n

log4j.rootLogger=info, stdout
# basic log level for all messages
log4j.logger.org.hibernate=info

# SQL statements and parameters
log4j.logger.org.hibernate.SQL=debug
log4j.logger.org.hibernate.type.descriptor.sql=trace

Using this configuration, Hibernate writes all executed SQL INSERT, UPDATE and DELETE statements to the log file. So, you can exactly see when and which statements Hibernate executed.

19:13:35,772 DEBUG [org.hibernate.SQL] - 
    select
        professor0_.id as id1_1_0_,
        professor0_.firstName as firstNam2_1_0_,
        professor0_.lastName as lastName3_1_0_ 
    from
        Professor professor0_ 
    where
        professor0_.id=?
19:13:35,773 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [1] as [BIGINT] - [1]
19:13:35,774 TRACE [org.hibernate.type.descriptor.sql.BasicExtractor] - extracted value ([firstNam2_1_0_] : [VARCHAR]) - [Jane]
19:13:35,774 TRACE [org.hibernate.type.descriptor.sql.BasicExtractor] - extracted value ([lastName3_1_0_] : [VARCHAR]) - [Doe]
19:13:35,775 DEBUG [org.hibernate.SQL] - 
    update
        Course 
    set
        endDate=?,
        name=?,
        professor_id=?,
        startDate=? 
    where
        id=?
19:13:35,776 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [1] as [DATE] - [2019-05-31]
19:13:35,776 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [2] as [VARCHAR] - [Software Development 1]
19:13:35,776 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [3] as [BIGINT] - [1]
19:13:35,776 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [4] as [DATE] - [2018-08-15]
19:13:35,777 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [5] as [BIGINT] - [1]

Learn more about JPA

Almost all Java projects that store information in a relational database use JPA with Hibernate or EclipseLink as its most popular implementations. That makes a solid understanding of JPA one of the most in-demand skills in the Java world.

If you haven’t used JPA yet or your understanding of it is just not as solid as it should be, you need to learn more about it so that you can use it in your projects and include it in your resume with confidence.

But don’t worry, that’s much easier and requires less time than you might expect. I have been using JPA for the last 15 years, and I spend most of my time implementing and optimizing JPA-based persistence layers for large, enterprise-scale applications. I have put all this experience into a beginners training. It shows you in a few hours how to use the JPA specification and provides you with a solid understanding of its most important concepts.

Sounds interesting? Then I hope to see you in my JPA for Beginners online training. It’s an on-demand, online training that consists of several pre-recorded videos, which fit easily into a busy schedule.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.