Each week I write a blog post which describes what I learned that week. I write these blog posts for two reasons.
First, I want to keep track of my personal development and writing regular blog posts is a great way to do it.
Second, I want to share my findings with you. I hope that you can use some of them in your daily work.
Let’s get started and find out what I learned in week 37.
What I Learned in Week 37
First, Use The Index, Luke!. I have noticed that the popularity of different ORM libraries has created an atmosphere where developers tend to treat relational database as a second class citizen.
I find it a bit depressing that developers might spend a lot of energy for optimizing their code without paying any attention to the database. It is sad because indexing is an easy way to optimize SQL queries. Don’t overlook it.
Second, The byte order mark (BOM) can be a pain in the ass. Let's assume that you have to read a CSV file and insert its data to the database. Also, let's assume that the first item of each line is a long and you have to transform it into a Long object when you process the line.
What happens when you process the first line of the CSV file?
If a BOM is found, a NumberFormatException is thrown because the first item is not a parseable long (I assume that you used the parseLong(String s) method of the Long class).
Luckily this problem is quite easy to solve. You can exclude the BOM by using the BOMInputStream class. This handy utility class is provided by the commons-io library.
Third, Understand the JPA fetch strategies. The default fetch types are:
- The default fetch type of the many-to-many relationship is lazy.
- The default fetch type of the many-to-one relationship is eager.
- The default fetch type of the one-to-many relationship is lazy.
- The default fetch type of the one-to-one relationship is eager.
So, what should we do with this information? We should take this into account when we are creating the domain model of our application. This week I had to solve some performance problem of an application which has a fairly complex domain model. The lessons which I learned from this are the following:
- Never use eager fetching on a tree structure.
- If you are using one-to-one relationships, avoid bidirectional relationships.
- If you have to use bidirectional one-to-one relationship, use lazy fetching if possible.
Unfortunately, JPA2 is very inflexible with eager/lazy fetching. (this post has been removed) The rules I mentioned are a good start. Unfortunately, it seems that there is no "general" solution for performance problems related to JPA.
I am starting to wonder that using JPA means that we spend less time writing code and more time debugging/profiling it.
Fourth, You can use the @Access annotation for configuring how the JPA2 provider accesses the persistent state of the entity. If are interested in how (and why) to do this, read this blog post.
Fifth, Don't let your past experiences dictate your expectations for the future.
Most of us are specialized in something. I am specialized in developing web applications. Does this mean that I don't want to or cannot do anything else? Of course not, but sometimes I forget that a web application isn't always a good solution to the customer's problem.
Let me explain.
This week I was talking with a potential customer, and I assumed that he wanted us to implement a web application which solves his problem. I remember thinking that it is going to be hard if we have to support old and shitty browsers. Then I spoke up and said:
It is going to hard to implement interactive interface if we have to support older versions of IE.
The customer answered:
Oh, it does not have to be a web application. A standalone application is fine to me
I was blown away. I realized that my past experience made me assume that he wants a web application. That was a mistake which might have been costly.
If you find yourself thinking this way, just pop the question. Asking doesn't cost you anything, and you might get an answer which you didn't expect.
What Did You Learn This Week?
Share your learning experiences or other comments on the comment section.
This week's learning's are really interesting. while reading about your whole week experiences, i too learn useful things from it.
Great. That means that I should continue writing these learning reports.
Interesting, I didn't know that JPA fetch type defaults are bound to the arity of the relationships. Good to know. So your learning this week, my learning this week :-)
I wonder what you think of JPA 2.1's (JEE 7's) support for NamedEntityGraphs. From what I understand, with those, you can explicitly specify fetch graphs for each entity and use them ad-hoc in the context of a concrete query, instead of globally across an application.
In my opinion, they're just another way to circumvent the best way to solve such problems: Write explicit SQL.
Besides, if you liked http://use-the-index-luke.com, you'll certainly love Markus Winand's book SQL Performance Explained (http://sql-performance-explained.com). It contains much more detailed content than his indexing blog / website.
Great! Good to hear that you learned something new.
I have mixed feelings about NamedEntityGraphs. I understand that there was a "need" to add something like this to the JPA specification. However, in the same time I feel that this only adds extra complexity which might not be as useful as you would think (this whole eager vs. lazy thing is a mess already).
So, I have to agree with you on this one!
I have been meaning to order that book for a while now. I will definitely do it soon because I have a feeling that it will be useful in my next project (and of course the current one).
Well, we'll see where NamedEntityGraphs will lead us. I am looking forward to Adam Bien adding some sections to his upcoming JEE 7 best practices book:
Being a strong JEE advocate, I'm sure he'll essentially stress the "good parts"