Saturday, May 4, 2013

JPA - Basic Projections

In my last post: JPA - Should I become a laziness extremist? - I mentioned about the possibilities of improving JPA usage - one of them is using Projections.

Projection is a subset of entities' properties. It can be represented as dedicated class (or classes), and mapped either as the database view based entity, or using constructor expressions [1][2]. The clue of this solution is having very limited entities tree (or no tree at all, as in my example) comparing to original entity (Employee). We need to display employee name, thus we build the projection having employee name and ID only. As you will see below, using projections leads to single SQL query, instead of bunch of SQL queries (see example in JPA - Should I become a laziness extremist?)

Database view based entities


What we need in this case is simple JPA entity, mapped to any database view (or table if desired properties are in one table).

Now we can run JPQL query:

select employee from ViewBasedEmployeeNameProjection employee order by employee.name

which in turn will execute one single SQL query:

select EMPLOYEE_ID, EMPLOYEE_NAME from EMPLOYEE order by EMPLOYEE_NAME

Using this method you have to remember that you can choose anything for the projection ID, as long as it uniquely identifies each projection. 

Constructor expressions


What we need in this case is a class representing the projection with constructor having parameters corresponding to all properties in the projection.
 
Now we can run JPQL query:

select new com.blogspot.vardlokkur.domain.EmployeeNameProjection(employee.employeeId, employee.name) from Employee employee order by employee.name

which in turn will execute one single SQL query:

select EMPLOYEE_ID, EMPLOYEE_NAME from EMPLOYEE order by EMPLOYEE_NAME

This method has some disadvantages:
  • adding new projection properties increases number of constructor parameters
  • projection class name is included in JPQL query, which may lead to refactoring problems
Second disadvantage can be solved with Querydsl, which also gives you few more possibilities of building projections, but that will be subject of my next post :) 

To be continued ...

Few links for the dessert

  1. JPQL Constructor Expressions
  2. Result Classes (Constructor Expressions)


Follow-ups:


This article has been republished on Dzone's Javalobby (05/06/2013).

Saturday, April 27, 2013

JPA - Should I become a laziness extremist?

When you spoke with the Developers about mapping objects to relational databases, they very often complain about poor JPA performance, unpredictable behavior of JPA Providers, etc. Usually at some point of the conversation you will hear: "Let's drop this technology at all, we've seen something much better on the conference last month. We will use it in our projects instead of JPA and develop them happily ever after." - Sounds familiar? :)

It's nothing wrong in learning new technologies, in fact you should do it constantly, to improve your skills and knowledge, but when you have problems with one of them, will you choose an easy path to another technology, or ask yourself: "Am I using it in a right way?"

Let's look at the JPA usage example. Suppose that we have simple database, mapped to the entities:


and we have to display all employee names, regardless their employer (and department). Nothing easier ;) - simple JPQL query will do that:

select employee from Employee employee order by employee.name

Many developers finish at this point, and celebrate with Friends another successful JPQL query in their life ;), but some of us have this strange feeling, that something creepy is lurking beneath the shiny surface. SQL queries produced by the JPA provider (ex. Hibernate) will reveal the truth: 
select [...]  from EMPLOYEE employee0_ order by employee0_.EMPLOYEE_NAME

Nothing special, so far :), but here comes the naked truth:
select [...] from DEPARTMENT department0_ left outer join EMPLOYER employer1_ on department0_.EMPLOYER_ID=employer1_.EMPLOYER_ID where department0_.DEPARTMENT_ID=?
select [...] from EMPLOYER employer0_ where employer0_.EMPLOYER_ID=?
select [...] from DEPARTMENT department0_ left outer join EMPLOYER employer1_ on department0_.EMPLOYER_ID=employer1_.EMPLOYER_ID where department0_.DEPARTMENT_ID=?
select [...] from DEPARTMENT department0_ left outer join EMPLOYER employer1_ on department0_.EMPLOYER_ID=employer1_.EMPLOYER_ID where department0_.DEPARTMENT_ID=?
select [...] from DEPARTMENT department0_ left outer join EMPLOYER employer1_ on department0_.EMPLOYER_ID=employer1_.EMPLOYER_ID where department0_.DEPARTMENT_ID=?
What the heck?! What are these queries for?! - Well the reason lies in default fetch attribute values for @ManyToOne annotations, which is EAGER. My database holds 2 Employers, one of them has 4 Departments, while second one hasn't any. When the Employee is loaded, JPA provider loads by default all EAGER associations (in our case both Department, and Employer), thus we have the additional queries. As you see above the JPA provider is clever enough to load both Employer and Department at once, when it is possible.

You've just found magical JPQL query fetching all the database content at once :). Does this situation remind you something in the past? ;)

What can we do about it? - My Friend, all you need is a laziness :) - Don't use EAGER unless it is REALLY needed (and remember that @ManyToOne and @OneToOne annotations use it by default).

You may call me a lunatic, or laziness extremist at this point :) and ask: Have you ever encountered LazyInitializationException, Bro!? Have you heard of all the mess with lazy loading problems!? Performance degradation, etc. ... Of course I did :), but don't you think that if we are getting in such troubles with JPA, maybe we use it in a wrong way?!

What we do usually in Web Applications is presenting or editing some data on UI, and usually it is only small subset of specific entities' properties. Doing it requires fetching the entities tree from the database - without batting an eye, we ask Entity Manager: give me all Employees, sorted by name, with all related entities, and then complain on degraded performance!

We don't care what we fetch from the database, because Entity Manager will do the donkey work for us. We get LazyInitializationException, so what! We will use Open Entity Manager in View pattern, and silence this stupid exception!

Give a me a break! Don't you think it's a dead end? :) - It's about time to change something :) There are sophisticated methods which you can use in your projects, like CQRS for example, along with possibilities already existing in JPA, which can help you change the bad manners described by me in this post.

To be continued ...

Few links for the dessert:




Follow-ups:


This article has been republished on Java Code Geeks (05/01/2013), and on Dzone's Javalobby (05/01/2013).

Saturday, April 6, 2013

JPA - Hibernate - Type mapping on package level

When we are finally mature enough to use some custom types mapping in JPA, we usually stuck with some provider specific solution, because JPA itself doesn't define any mechanism for doing it. Let me show you an example of custom type mapping definition for one of the JPA providers - Hibernate.

Suppose that we use Joda Money in our project, and have an entity with property having type Money. There are already pretty nice type mapping implementations for Money, provided by Jadira - User Types project. All we have to do is just let Hibernate know that we want to use specific type mapping.

When you look at the Hibernate Docs, Section 5.1.4.1.1: Type, you'll see few possibilities, starting from the simplest - using @Type annotation on each property having Money type. This choice can be good if you have only one, or very few, properties of this type in your domain mapping. It is very probable that sooner or later, when your project will grow enough, there will be more and more of them, and you end up with many similar lines defining the same type mapping.

If you aren't a big fan of repeating yourself, or you don't trust in refactorings made by your apprentices ;), you should consider another way, using @TypeDefs and @TypeDef annotations.

As you may read in Hibernate documentation: "These annotations can be placed at the class or package level." - Let's focus on the second option - package level.

We will place these annotations in package-info.java for our domain entities holding package (see: Java Language Specification - 7.4.1. Named Packages). It will look like this:

Now, when you map the property using Money type, you can do it without additional type mapping specification, just like this:

One technical note, before you become happy Money mapping user ;) - Because PersistentMoneyAmount uses single column (holding amount) for Money mapping, it requires defining of currency which will be used along with the amount. The default currency can be defined as Persistence Unit property: jadira.usertype.currencyCode

PS. Don't treat the above Money example as the guideline of Joda Money mapping :), there are probably better ways of doing it, see Jadira User Types blog.

Few links for the dessert:





Follow-ups:


This article has been republished on Java Code Geeks (04/09/2013), and on Dzone's Javalobby (04/15/2013).

Sunday, December 2, 2012

Spring's Web MVC - Redirect to the Memory Leak

They say that one rock can cause an avalanche. Lately, one of my Colleagues, Marcin Radoszewski, gave me such a rock. You'll probably never guess what it is, but there is a chance, that you use it in many of your Web Applications. Allow me to introduce this rock to you :)

You probably well know redirect after post pattern. Using Spring Framework you have few ways to implement it, let's focus on one of them, returning the target URL as the String with redirect: prefix.

Suppose that we have controller using this method of redirecting, and we have to pass some parameters during the redirect, let it be some entity ID for example:

@RequestMapping(method = RequestMethod.POST)
public String onPost(...) {
    ...
    return "redirect:form.html?entityId=" + entityId;
}

As you see, our rock doesn't look dangerous, it even doesn't look suspicious :) - What the heck is wrong with that?! - you may ask. Well, to explain that, we have to take a look at the way how Spring Framework handles the value returned by you.

You may start from reading Resolving views in Spring Framework documentation, and then take a closer look at the source code of AbstractCachingViewResolver, which is base class for many different View Resolvers in Spring, including: JSP, FreeMarker, Velocity, Jasper Reports, Tiles and XSLT view resolvers.

When resolveViewName method is called on AbstractCachingViewResolver it uses HashMap based view cache to speed up view resolving in the future calls, and cache key is by default created using view name and current locale.

Now to the clue :) - when you use the above method of redirecting, Spring Framework uses the whole String returned from your controller's method as the view name, including all parameters included in the target URL. Each time you perform the redirect, the parameters may vary, thus such a redirect will leave one additional entry in view cache of  AbstractCachingViewResolver, causing memory leak.

How soon that will kill my application? - you may ask. That depends on the amount of memory assigned to JVM, and the number of performed redirects :) - I've made some tests using: -Xmx64M option, with simple application build from only one controller - see this example. After about 76400 redirects the application died with OutOfMemoryError: Java heap space.
 


Follow-ups:


This article has been republished on Java Code Geeks (12/07/2012), and on Dzone's Javalobby (12/10/2012).

Monday, August 13, 2012

JPQL - pagination on Oracle Database with Hibernate

In your daily work, you rely on many different libraries, trusting they will serve you well, being perfect piece of code ... do you? ... really?! Then it's time to realize that you are perfectly wrong :) Increasing complexity of code leads to new possibilities of making errors :) Many of them are lurking in the libraries used by you, even if they are used for years by thousands of developers.

Let's find some example. Suppose that we are using JPA, and have an entity named Employee, which contains at least two properties: name and id. Suppose that we want to display all employees ordered by name, and paginated. To fetch them from the underlying database we will need JPQL query like this:

select e from Employee e order by e.name

We will paginate it using setFirstResult and setMaxResults methods of javax.persistence.Query interface. Now we need a JPA provider and database to make it work, let's choose Hibernate, and Oracle (10+).

At first try everything works perfectly :) - but let's assume that we have employees sharing the same name, for ex. 20 of them having name 'Smith' (identifiers between 1 and 20), 10 having name 'Donovan' (identifiers between 21 and 30) and 10 having name 'Johnson' (identifiers between 31 and 40) - total 40 employees. Let's try to display 5 employees on single page, and see what will happen:

Page 1 - employees having ID: 21, 25, 24, 23, 22 - all having name 'Donovan' - good :)
Page 2 - employees having ID: 26, 25, 24, 23, 22 - all having name 'Donovan' - but 4 of them were already displayed on first page (!)
Page 3 - employees having ID: 31, 35, 34, 33, 32 - here comes the 'Johnson' name - good again :)
Page 4 - employees having ID: 36, 35, 34, 33, 32 - 'Johnson' again, and again 4 of them were already displayed on third page (!!)
Page 5 - employees having ID: 1, 17, 18, 19, 20 - here comes the 'Smith' name - good again :)
and finally the real surprise - Pages 6, 7 and 8 contains same employees - having ID: 16, 17, 18, 19, 20

Don't you think something is wrong here ?! ;) Well, the reason of this strange error is visible when you check SQL queries generated by Hibernate:

for the first 5 rows and:


for the rows 6 - 10 (and similar for next pages).

What the heck?! - you may say - These beautiful SQL queries are suggested for pagination on Oracle's website - see Tom Kyte's article: On ROWNUM and Limiting Results - sure :) - but the one who implemented it in Hibernate didn't read this article too deeply, skipping this important part:

One important thing about using this pagination query is that the ORDER BY statement should order by something unique. If what you are ordering by is not unique, you should add something to the end of the ORDER BY to make it so.

As you see, correct JPQL query leads to invalid SQL query for Hibernate / Oracle combination, and the error shows himself only for some combinations of data in the database - it is very difficult to spot because of that.

Do you still think that libraries used by you are perfect? :)

PS: This article has been created thanks to one of my Colleagues - Joanna Głowińska - her awesome work on SQL queries in some of our projects lead me to the above thoughts.



Follow-ups:


This article has been republished on Dzone's Javalobby (08/27/2012), with interesting comments from Gavin King, Karl Peterbauer, Andrew Thorburn, and Tomasz Wermiński.