April 22, 2010 | Category: Uncategorized

Modern Java: JPA

In the previous post, I showed how JSR-303 is making validation neater. I concluded that article with the Person bean looking like this:

@Data
public class Person {
    @NotNull @Size(min=1)
    private String firstName;
    @NotNull @Size(min=1)
    private String lastName;
    @Min(18)
    private int age;
}

If we know we have a valid bean, at some point we probably want to persist it so we can use it again. I won’t waste time on spelling out how much boilerplate code is written for raw JDBC calls as most developers have moved a level of abstraction up from that anyway, with great tools like Spring’s JdbcTemplate.

I also won’t go deeply into the history of ORM in Java, as a lot has already been said. The Java Persistence API (JPA) standardised fairly sensible ideas about how ORM should work, starting from real implementations (primarily Hibernate) and pulling together the main concepts. To prepare a bean for JPA persistence, we merely need to add an @Entity annotation and specify an @Id column (which I’m going to have to add to Person):

@Data @Entity
public class Person {
    @Id
    private Long id;
    @NotNull @Size(min=1)
    private String firstName;
    @NotNull @Size(min=1)
    private String lastName;
    @Min(18)
    private int age;
}

And that’s it. You can then use a properly configured EntityManager to persist() your class (the configuration details are largely implementation specific, but relatively lightweight).

There are a lot of options available to configure exactly how an entity should be persisted when passed into an EntityManager. Again, I won’t cover them all, but it’s generally considered best practice to state your table and column names explicitly (rather than relying on convention, as I have above) and you’ll often want to make use of the built-in optimistic concurrency support to stop multiple changes happening at once.

@Data @Entity @Table(name="people")
public class Person {
    @Id @Column(name="id");
    private Long id;

    @Version @Column(name="version")
    private int version;

    @NotNull @Size(min=1)
    @Column(name="first_name")
    private String firstName;

    @NotNull @Size(min=1)
    @Column(name="last_name")
    private String lastName;

    @Min(18)
    @Column(name="age")
    private int age;
}

As a bonus, if you use a JPA2 provider AND have a JSR-303 validation implementation in your classpath, the default behaviour will be for your bean to get validated before it gets persisted, so you wouldn’t have to explicitly call the validator any more.

Again, there’s a lot more to be said about JPA, and the use cases that it supports (I haven’t touched on object-graphs, embedded collections, or the Java persistence query language), but you should have a flavour for it.