Thursday, April 22, 2010

Making JPA Play Nice With a DataTable

It can be done!

No... really... it can!

Lesson learned for today... The following two statements:

Query query = em.createQuery("Select p from Chapters p");
Query query = em.createNativeQuery("Select * from chapters");

are NOT interchangeable.

I'm serious.

don't believe me? Go ahead and try it. Do a

query.getResultList();

and then feed that output to a JSF DataTable and watch what happens.

The first one will work. The second: KABOOM.

You see, the getResultList() method returns a List. Simple, right? Nah. Not really. You see, at issue here is what, exactly that List contains.

Using the EclipseLink SQL-like language in the createQuery does two things: First, it abstracts the database so that the command will run no matter what kind of backend you're using. Second, it returns a List of objects of the type specified in the query. In the first statement, the createQuery method, the word 'Chapters' is capitalized because it refers to a class not a table. It will return a List of type Chapters (in this case) and when we wire that up later to the DataTable component it will happily cast the objects as Chapters objects (As specified in the faces-config.xml) and display them.

On the other hand, running that createNativeQuery method is asking for trouble. It's straight SQL, and in this example would run fine in prettymuch any database, but not all databases are created equal and the more complex your query is, the more committed you are to the database you originally wrote it for. Know what the other problem is? Yep, by now you should have guessed it... you'll get back a List of Objects.

Good luck trying to cast those as Chapters objects.

The EL isn't going to be much help so a list of generic Objects gets passed to your poor, unsuspecting DataTable and KABOOM! You'll be Googling this: "java.lang.NumberFormatException: For input string:"

See, when this big list of generic objects gets sent to the DataTable it doesn't know how to interpret these things, the EL is relying on the Chapters bean for guidance on finding the fields but these aren't Chapters objects. They're generic lumps of data that came from a database. It appears the EL is trying to stick the index of the elements into the first field you've defined in your table. That's an int. Bad mojo.


No comments:

Post a Comment