Professional Documents
Culture Documents
You can find lots of articles and videos explaining how to write
maintainable Java code. All of that advice is also valid for your
persistence layer. In the end, it’s still Java code, isn’t it?
But that advice isn’t enough.
You can follow general Java best practices and still build a messy
persistence layer. JPA and Hibernate heavily rely on String
references, which quickly get unmaintainable, and the managed
lifecycle introduces invisible functionalities and requirements.
So, you need to take it one step further and not only follow best
practices for Java. You also need to apply specific best practices for a
persistence layer using JPA or Hibernate. But don’t worry. That’s
much easier than you might think.
...
}
www.thoughts-on-java.org
Best Practices for Readable and Maintainable Code
You can then use these constants in your code instead of magic
Strings.
By doing that, you get a few things back that you lost in the first
place:
You can use your IDE to find all places in your code that call a
specific query or use any other named element.
It gets much easier to find and reuse existing queries that
already fetch the required information.
If you need to rename an attribute or any other named element,
you simply change the value of the String constant.
You can then use the Order_ class with most of JPA’s APIs. I use it in
the following example to select the orderNumber and customer
attributes of the Order entity.
www.thoughts-on-java.org
Best Practices for Readable and Maintainable Code
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Tuple> cq = cb.createTupleQuery();
Root<Order> root = cq.from(Order.class);
cq.multiselect(root.get(Order_.ORDER_NUMBER), root.get(Order_.CUSTOMER));
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id = null;
@ManyToOne(fetch = FetchType.LAZY)
private Customer customer;
...
}
www.thoughts-on-java.org
Best Practices for Readable and Maintainable Code
In addition to that, it gives you the freedom to implement the getter
and setter methods in any way you want. By using field-based access,
you tell Hibernate to use reflection to set or get the value of an
attribute. That enables you to implement the getter and setter
methods in a way that makes your entity easy to use.
You could, for example, introduce a utility method that manages a
bidirectional association. It’s easy to forget to update both ends of an
association, so why not offer a method for it? It’s a general best
practice for to-many associations.
@Entity
@Table(name = "purchaseOrder")
public class Order {
public Set<OrderItem> getItems() {
return this.items;
}
www.thoughts-on-java.org
Best Practices for Readable and Maintainable Code
@Entity
@Table(name = "purchaseOrder")
@NamedQuery(name = Order.QUERY_BY_CUSTOMER,
query = "SELECT o FROM Order o WHERE o.customer = :"
+ Order.PARAM_CUSTOMER)
public class Order {
...
}
By using a named bind parameter in your query, you make the code
that calls the query easier to understand. Everyone can immediately
see which value it sets for which bind parameter.
TypedQuery<Order> q = em.createNamedQuery(Order.QUERY_BY_CUSTOMER,
Order.class);
q.setParameter(Order.PARAM_CUSTOMER, "Thorben Janssen");
List<Order> orders = q.getResultList();
www.thoughts-on-java.org
Best Practices for Readable and Maintainable Code
The easiest and most readable way to set a query hint is to use
Hibernate’s org.hibernate.annotations.QueryHints and
org.hibernate.graph.GraphSemantic classes with String constants for
most query hints. Using that class, you can rewrite the previous
example to use the GraphSemantic.FETCH constant instead of
javax.persistence.fetchgraph.
www.thoughts-on-java.org