Showing posts with label Hibernate. Show all posts
Showing posts with label Hibernate. Show all posts

Monday, August 20, 2012

Hibernate – Fetching Strategies Examples

Hibernate has few fetching strategies to optimize the Hibernate generated select statement, so that it can be as efficient as possible. The fetching strategy is declared in the mapping relationship to define how Hibernate fetch its related collections and entities.

Fetching Strategies

There are four fetching strategies
  • fetch-”join” = Disable the lazy loading, always load all the collections and entities.
  • fetch-”select” (default) = Lazy load all the collections and entities.
  • batch-size=”N” = Fetching up to ‘N’ collections or entities, *Not record*.
  • fetch-”subselect” = Group its collection into a sub select statement.

For detail explanation, you can check on the Hibernate documentation.

Fetching Strategies Examples

Here’s a “one-to-many relationship” example for the fetching strategies demonstration. A stock is belong to many stock daily records.

Lets explore how fetch strategies affect the Hibernate generated SQL statement.

Fetch=”Select” Or @Fetch(FetchMode.SELECT)

This is the default fetching strategy. it enabled the lazy loading of all it’s related collections.

Output:
Hibernate: 
    select ...from mkyong.stock
    where stock0_.STOCK_ID=?
 
Hibernate: 
    select ...from mkyong.stock_daily_record
    where stockdaily0_.STOCK_ID=?

Hibernate generated two select statements
1. Select statement to retrieve the Stock records -session.get(Stock.class, 114)
2. Select its related collections – sets.iterator()

Fetch=”Join” Or @Fetch(FetchMode.JOIN)

The “join” fetching strategy will disabled the lazy loading of all it’s related collections.

Output:
Hibernate: 
    select ...
    from
        mkyong.stock stock0_ 
    left outer join
        mkyong.stock_daily_record stockdaily1_ 
            on stock0_.STOCK_ID=stockdaily1_.STOCK_ID 
    where
        stock0_.STOCK_ID=?

Hibernate generated only one select statement, it retrieve all its related collections when the Stock is initialized. -session.get(Stock.class, 114)
1. Select statement to retrieve the Stock records and outer join its related collections.

Batch-Size=”10″ Or @BatchSize(Size = 10)

This ‘batch size’ fetching strategy is always misunderstanding by many Hibernate developers.

What is your expected result, is this per-fetch 10 records from collection? See the Output
Hibernate: 
    select ...from mkyong.stock
    where stock0_.STOCK_ID=?
 
Hibernate: 
    select ...from mkyong.stock_daily_record
    where stockdaily0_.STOCK_ID=?

The batch-size did nothing here, it is not how batch-size work. See this statement.
The batch-size fetching strategy is not define how many records inside in the collections are loaded. Instead, it defines how many collections should be loaded.
— Repeat N times until you remember this statement —

You want to print out all the stock records and its related stock daily records (collections) one by one.
No batch-size fetching strategy
Output:
Hibernate: 
    select ...
    from mkyong.stock stock0_
 
Hibernate: 
    select ...
    from mkyong.stock_daily_record stockdaily0_ 
    where stockdaily0_.STOCK_ID=?
 
Hibernate: 
    select ...
    from mkyong.stock_daily_record stockdaily0_ 
    where stockdaily0_.STOCK_ID=?
 
Keep repeat the select statements....depend how many stock records in your table.

If you have 20 stock records in the database, the Hibernate’s default fetching strategies will generate 20+1 select statements and hit the database.

1. Select statement to retrieve all the Stock records.
2. Select its related collection
3. Select its related collection
4. Select its related collection
….
21. Select its related collection
The generated queries are not efficient and caused a serious performance issue.


Enabled the batch-size=’10′ fetching strategy
Let see another example with batch-size=’10′ is enabled.
Output:
Hibernate: 
    select ...
    from mkyong.stock stock0_
 
Hibernate: 
    select ...
    from mkyong.stock_daily_record stockdaily0_ 
    where
        stockdaily0_.STOCK_ID in (
            ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
        )

Now, Hibernate will per-fetch the collections, with a select *in* statement. If you have 20 stock records, it will generate 3 select statements.
1. Select statement to retrieve all the Stock records.
2. Select In statement to per-fetch its related collections (10 collections a time)
3. Select In statement to per-fetch its related collections (next 10 collections a time)

With batch-size enabled, it simplify the select statements from 21 select statements to 3 select statements.

Fetch=”Subselect” Or @Fetch(FetchMode.SUBSELECT)

This fetching strategy is enable all its related collection in a sub select statement.

Output:
Hibernate: 
    select ...
    from mkyong.stock stock0_
 
Hibernate: 
    select ...
    from
        mkyong.stock_daily_record stockdaily0_ 
    where
        stockdaily0_.STOCK_ID in (
            select
                stock0_.STOCK_ID 
            from
                mkyong.stock stock0_
        )

With “subselect” enabled, it will create two select statements.
1. Select statement to retrieve all the Stock records.
2. Select all its related collections in a sub select query.



Conclusion The fetching strategies are highly flexible and a very important tweak to optimize the Hibernate query, but if you used it in a wrong place, it will be a total disaster (You're screwed dude!).


Tuesday, July 31, 2012

OneToMany Relation with Non PK Columns

While goofing around @ my office my Boss told me about an issue he was facing while trying to map a OneToMany relation, but instead of using the classical PK on one side and FK on the other side, he wanted to define the relationship between tables with nonKey columns. I still don't know why but this situation reminded me when I was having a hard time playing with 1:1 relations.
Anyway the fact is that we need find a workaround for this, and as is well known if you don't define anything on Hibernate (Annotations), by default is going to use the default values, right?

My approach is simple, by just defining after the OneToMany annotation which columns I'll join, in order to get this Set. Probably my Child table has a PK which doesn't have anything to do with the column I'm using to do the join with the Parent (which is a valid scenario - and BTW is what's happening now) Why don't you give it a try! On my case one of colleagues tried and I got another satisfied customer ;)

Sunday, July 1, 2012

Logging Optimistic Concurrency Exceptions: org.hibernate.StaleObjectStateException and JBPM

When it is running in a cluster configuration, the jBPM synchronizes with the database by using optimistic locking. This means that each operation is performed in a transaction and if, at the end, a collision is detected, then the transaction in question is rolled back and has to be handled with a retry. This can cause org.hibernate.StateObjectStateException exceptions. When this happens, Hibernate will log the exceptions with a simple message: optimistic locking failed

Hibernate can also log the StateObjectStateException with a stack trace:
15:35:07,123 [DispatcherThread] ERROR [AbstractFlushingEventListener] Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.pvm.internal.job.TimerImpl#960071]
 at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1769)
 at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2412)
 at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2312)
 at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2612)
 at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:96)
 at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
 at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
 at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
 at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
 at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
 at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
 at org.jbpm.pvm.internal.tx.HibernateSessionResource.prepare(HibernateSessionResource.java:56)
 at org.jbpm.pvm.internal.tx.StandardTransaction.commit(StandardTransaction.java:107)
 at org.jbpm.pvm.internal.tx.StandardTransaction.complete(StandardTransaction.java:64)
 at org.jbpm.pvm.internal.tx.StandardTransactionInterceptor.execute(StandardTransactionInterceptor.java:57)
 at org.jbpm.pvm.internal.svc.EnvironmentInterceptor.executeInNewEnvironment(EnvironmentInterceptor.java:53)
 at org.jbpm.pvm.internal.svc.EnvironmentInterceptor.execute(EnvironmentInterceptor.java:40)
 at org.jbpm.pvm.internal.svc.RetryInterceptor.execute(RetryInterceptor.java:56)
 at org.jbpm.pvm.internal.svc.SkipInterceptor.execute(SkipInterceptor.java:43)
 at org.jbpm.pvm.internal.jobexecutor.DispatcherThread.acquireJobs(DispatcherThread.java:126)
 at org.jbpm.pvm.internal.jobexecutor.DispatcherThread.run(DispatcherThread.java:67)

To remove these stack traces, set the org.hibernate.event.def.AbstractFlushingEventListener class to FATAL. Do so in log4j by using the following configuration:
log4j.logger.org.hibernate.event.def.AbstractFlushingEventListener=FATAL

Remember, this exception will not affect your process execution!, you can ignore it :)

Source: http://docs.redhat.com/docs/en-US/JBoss_Enterprise_SOA_Platform/5/html/JBPM_Reference_Guide

Sunday, February 5, 2012

StaleObjectStateException on JBPM4

When I was doing some testing to my recently implemented JBPM4 process, I faced a really ugly error, which ended abruptly my process :(

Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.pvm.internal.job.TimerImpl#17]

After researching on Jboss.org, I just found very few bread crumbs instead of the whole slice of bread:
StaleObjectException on Timer execution
My process was different, because mine was completely ASYNC, then I realize, what would happen if I make SYNC just the WAIT state (which was causing the problem) and keep ASYNC my other states. After my first test, I got what I was expecting :D

Saturday, December 24, 2011

OneToMany Mapping

I faced this issue on August, let me explain you the situation, I had a Table called PURCHASE, with a 1:N Relationship with PURCHASE_MODULE and TRANSACTION tables
TRANSACTION >-----PURCHASE-----< PURCHASE_MODULE

First thing, How do I represent that using annotations (Hibernate):
Now what I want is each time I populate Purchase and set both List's (transactions and purchaseModules) and Invoke a SAVE for Purchase, the 3 tables will be impacted( there will be at least 3 INSERTs): purchaseDAO.save(purchase)
But this wasn't working as I expected, because no matter if I populated both ArrayList's (List) I never saw more than 1 Insert on my console.

Then the spark I was looking for! Inspiration came to me :P
On the Annotation @OneToMany there is an additional attribute I didn't include: cascade (The operations that must be cascaded to the target of the association)

On my case I don't care, so I just include ALL operations :P

Saturday, December 3, 2011

ClassCastException with Hibernate: org.hibernate.type.DateType cannot be cast to org.hibernate.type.VersionType

I ran into a weird error when starting a Seam App with JPA (Hibernate) on JBoss

2011-08-03 14:30:17,938 [main] ERROR [org.jboss.deployment.scanner.URLDeploymentScanner] Incomplete Deployment listing:

--- MBeans waiting for other MBeans ---
ObjectName: persistence.units:ear=mainsite.ear,jar=kaptest_domain.jar,unitName=commonDatabase
  State: FAILED
  Reason: java.lang.ClassCastException: org.hibernate.type.DateType cannot be cast to org.hibernate.type.VersionType
  I Depend On:
    jboss.jca:service=DataSourceBinding,name=jdbc.CommonTransactionDS
  Depends On Me:
    jboss.j2ee:ear=mainsite.ear,jar=kaptest_domain.jar,name=AdobeMeetingDAO_Seam_Impl,service=EJB3
    jboss.j2ee:ear=mainsite.ear,jar=kaptest_domain.jar,name=AdobeProductDAO_Seam_Impl,service=EJB3
    jboss.j2ee:ear=mainsite.ear,jar=kaptest_domain.jar,name=AdobeUserDAO_Seam_Impl,service=EJB3
    jboss.j2ee:ear=mainsite.ear,jar=kaptest_domain.jar,name=AverageRatingServiceImpl,service=EJB3
    jboss.j2ee:ear=mainsite.ear,jar=kaptest_domain.jar,name=BookstoreProductServiceImpl,service=EJB3
    jboss.j2ee:ear=mainsite.ear,jar=kaptest_domain.jar,name=BookstoreSearchServiceImpl,service=EJB3
...
...
WHAT??? java.lang.ClassCastException: org.hibernate.type.DateType cannot be cast to org.hibernate.type.VersionType

Anyway, for some reason, hibernate reverse engineer puts the @Version annotation to fields called timestamp as it expects it to be of type java.sql.Timestamp
Unfortunatly, my property was of type java.util.Date which is incomaptible with the @Version annotation.
I removed the @Version and it worked!

Sunday, November 20, 2011

Primary key @OneToOne mapping in Hibernate (JPA)

My main objective is to save/insert as many POJO's as possible with the minimum # of calls to save method. That's why I'm relate them.

But there is a special relationship which it's not clearly documented on the official documentation, and that's why you'll see this entry here :)

.The problem is that I have 2 tables COURSE_ACCESS and COURSE_ACCESS_STATUS:
---------------
COURSE_ACCESS
---------------
*id
...
---------------

---------------------
COURSE_ACCESS_STATUS
---------------------
*course_access_id
...
---------------------

The relationship is 1:1. COURSE_ACCESS is the "parent" table, because that one has the SEQUENCE which generates the PK on "id" column.

Now what I want is when I save COURSE_ACCESS, COURSE_ACCESS_DATA should be saved too. Just like this
How I did it?



And that's it!!! Easy isn't it?

Tuesday, August 9, 2011

Named Queries in Hibernate

After a code review, somebody asked me about the difference between Named Queries and write your own HQL in your methods (embedding HQL in our DAO's)
Interesting topic!

IMHO, I say that both scenarios are perfectly correct, but...
from Pro EJB 3 (Mike Keith):
"...we recommend named queries whenever possible. Persistence providers will often take steps to precompile JPQL named queries to SQL as part of the deployment or initialization phase of an application."

Although this book is on JPA, the general advice applies to Hibernate. However, since Hibernate caches parsed HQL/JPQL, you probably won't see a big performance gain.
One advantage of using named queries is that it gives you the option to override a query using a mapping file at deployment time without having to rebuild your application; useful if you need to tweak a query in production.
And for me the main advantage is that Hibernate parses the queries at startup so any errors will be detected promptly (This one is the most important advantage for me)

Wednesday, March 30, 2011

Accessing a PostgreSQL table using Hibernate

I was goofing around with PostgreSQL, and I wanted to give it a try, so I decided to replicate my Payment table from HSQLDB to PostgreSQL and I got something like this
CREATE TABLE "PAYMENTS"
(
  id_order integer NOT NULL,
  id_customer integer NOT NULL,
  total_amount_transaction double precision,
  transaction_number character varying(50),
  creation_ts timestamp with time zone,
  CONSTRAINT pk_payments PRIMARY KEY (id_order, id_customer)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE "PAYMENTS" OWNER TO payments;
As you well know with Hibernate the switch should be not very painful, and it won't have any impact on existing code!
But...Surprise!

The impact is not a huge impact but it's something really specific, and that's why I'm creating this post.

The usual steps to chnage from one DB to another DB is Hibernate is really simple:
This is my previous DataSource - Because, to accelerate the process I did the change locally before deploying this to my app server, so I can test locally using my existing JUnit test cases
And this is my new DataSource for PostgreSQL
Important: Remove the "defaultAutoCommit" attribute and add "defaultCatalog" attribute
This is my new Dialect

And this is the second Important detail:
Add double quotes to your table name!, just like this
My original code used to be
@Table(name = "PAYMENTS")


This is my new Payments DB :)

Hibernate did't again!

Wednesday, February 9, 2011

About Hibernate 3 plugin for Maven

In one of my previous entries, I had something really cool on my POM, which basically generated the DataBase based on my Entyties (or Domain objects), and that was the Hibernate 3 plugin for Maven
As you will see on the official documentation for that plugin, you can do a bunch of things, but it doesn't says anything about, generating Java classes based on the Tables, right? In other words, if I want my model java files (obtained by reveng) compiled, you don't need to run hbm2hbmxml.
I found the solution to this issue (unfortunately is not documented, and that's why you see it here):

Plugin configuration
hibernate.properties
hibernate.connection.username=root
hibernate.connection.password=secretit0
hibernate.connection.url=jdbc:mysql://127.0.0.1:3306/little_store
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.default_schema=little_store

model_reveng.xml
Then the last step is executing Maven:
mvn hibernate3:hbm2java

And we're ready to roll! :)

Wednesday, September 8, 2010

Log SQL Statements on Hibernate

Hibernate, in the end, is all about dispatching SQL statements. SQL is at the heart of communication with an RDBMS system, and it is extremely important when struggling through performance problems or other bugs, that you know what is going on. After all, knowing the executed SQL allows you to determine the number of queries to complete an O/R mapping task, not to mention that seeing SQL queries is critical to understanding how to optimize the queries via indices and other database settings.
There are two ways (due to the legacy of Hibernate) to enable SQL logging. The first is to simply enable SQL logging in the Hibernate configuration By setting the hibernate.show_sql to TRUE

This is a nice quick and dirty solution, but it is relatively inflexible. SQL statements are always logged to System.out when that property is enabled, and on some servers, System.out isn't accessible by the average developer; or is cluttered with a million other log statements.

Alternatively, Hibernate uses the Apache-Jakarta Commons Logging package, which means that it will utilize log4j , java.util.logging , or potentially another logging framework. Typically, log messages are sent to commons logging, and then they are dispatched to one of these logging frameworks. Then, those logging frameworks determine where the message should be sent (log files, sockets, emails, database records, system out, system err, etc). It is easy to see how using these log frameworks will increase the flexibility of log statements. With Hibernate, simply setting the org.hibernate.SQL logger to 'DEBUG' or 'ALL' will ensure that all SQL statements are logged to the console.


If you set up a log4j category for org.hibernate.type
Get it to write out to the same log file as the org.hibernate.SQL
The type one will list the parameters for you after the SQL e.g.
2006-07-28 09:57:12,061 DEBUG org.hibernate.SQL - insert into BASKET_LINE_ALLOC (LAST_UPDATED, QUANTITY, CUSTOMER_REF, NOTES, BRANCH_ID, FUND_ID, TEMPLATE_ID, 
BASKET_LINE_ALLOC_ID) values (?, ?, ?, ?, ?, ?, ?, ?) 
2006-07-28 09:57:12,081 DEBUG org.hibernate.type.TimestampType - binding '2006-07-28 09:57:12' to parameter: 1 
2006-07-28 09:57:12,081 DEBUG org.hibernate.type.IntegerType - binding '3' to parameter: 2 
2006-07-28 09:57:12,082 DEBUG org.hibernate.type.StringType - binding '' to parameter: 3 
2006-07-28 09:57:12,082 DEBUG org.hibernate.type.StringType - binding '' to parameter: 4 
2006-07-28 09:57:12,082 DEBUG org.hibernate.type.LongType - binding '511' to parameter: 5 
2006-07-28 09:57:12,082 DEBUG org.hibernate.type.LongType - binding '512' to parameter: 6 
2006-07-28 09:57:12,082 DEBUG org.hibernate.type.LongType - binding null to parameter: 7 
2006-07-28 09:57:12,082 DEBUG org.hibernate.type.LongType - binding '180030' to parameter: 8 

@Autowired and @Qualifier

"Your best friends could be @Autowired and @Qualifier"
I have to migrate data from DB2 to Oracle, both databases have the same structure, well, my Oracle has better design, but I'm reusing the some objects, like POJO's and DAO's, the only thing I changed were my mappings, because I have to keep my mappings for DB2 and for Oracle.
If I have the same DAO for both databases, what can I do?
daoApplicationContext.xml
As you can see, I have 2 different DAO's sharing the same Interface & Implementation, but each one belongs to a different "sessionFactory" serviceApplicationContext.xml
Nothing special, right? But now here it comes the interesting part, because @Autowired by itself it will inject the given bean in your ServiceImpl, but you must have only one bean of that type. In my case I have more than 1, so @Autowired will throw an error when loading the context.
Then it comes @Qualifier which will match based on the given name, and problem solved chavos!!!

Notes: I used org.springframework.beans.BeanUtils to create a copy of my bean (pojo) returned from DB2 into a non-persistent Pojo which I'll manipulate before inserting into Oracle (DB2 completes each column value with spaces to achieve the given size of that column, so each time you query a DB2 column you'll get a lot of extra spaces)

Wednesday, September 1, 2010

EmbeddedId in Hibernate, AnnotatedClasses

I had to do some inserts to a table with a composite PK:



Nothing special, I decided to use Hibernate with annotations (but what about the PK: just create another class -duh, but How can I tell hibernate this is my PK? @EmbeddedId and @Embeddable):
@Embeddable
Defines my composite PK
@EmbeddedId
Includes my composite Pk in my main Pojo
If you want to include in your sessionFactory (daoApplicationContext.xml) my annotated pojos, add this entry
As a reminder, if you want to use a propeties file to provide parameter for your DataSource, you have to do this:

Sunday, June 27, 2010

WebServices with CXF - Configuration files - web.xml

Sunday, June 13, 2010

WebServices with CXF - Configuration files II

I'll just include my Spring configuration files.
Why files? -I though Spring only needs an applicationConext??? Well... Because I prefer to split configuration files according to it's purpose:

  • One will have everything related to the Persistence layer
  • and the second one will have all my Business layer -services
Following this logic I should have another one for my Web layer

daoApplicationContext

serviceApplicationContext

When I met Annotations, I just felt in love with them, because one of the main advantages you gain is small configuration files.

On my next entry I'll cover my Apache CXF configuration file and how it fits.

Don't forget to add @Autowired, in case that you want to use this feature by

WebServices with CXF - Configuration files I

I'll show 2 basic configuration files: web.xml & my hibernate configuration file (mapping.cfg.xml)


As you noticed I'm using Spring MVC (see webApplicationServlet), but for now let's focus on Spring and CXF:

My 3 main configuration files are listed here, where the 3rd one is for CXF (really obvious file name) and to enable Apache CXF is so simple, Did you remember XFire?

This is not rocket science! So simple :)


Now let's see my (small) Hibernate configuration file (which I just called mapping.cfg.xml) Instead of using resource=, I'm using class=, because I don't have any hbm.xml file. I'm mapping directly to the class (due to Java Annotations, my mapping it was declared on each POJO).

Now what do you think? Is not as complex as looks like.

Saturday, April 17, 2010

WebServices with CXF - My Pojos & DAOs

First thing, is a good practice declaring methods equals and hashCode
You know what, I'll skip these methods on my code, eclipse can do it for you, don't be lazy!!!
And one more thing, as Architect it's a must declaring toString method, because when you're debugging these method it's going to be really helpful, and you know what... declare toString it's a must too.
The next step is explain what are those annotations, well they're Java 6 annotations, so we can skip some configurations and declare them into our code. I'll try to explain as simple as possible these annotations, let's analyze them:
What I'm doing here is just declaring that this POJO will be an Entity which maps to a table called EDITOR

Using Annotations, I declared that editorId is my PK which basically is AutoIncremental and to which column will be mapped. With columns is really easy.
But what about relations??? Like
BOOK >-- EDITOR
In this case I just declared what I needed to declare: One Editor has Many books using a List of Book, like in every mapping of Hibernate: the most common fetching strategy to be used will be LAZY; basically what I did was linking the current ENTITY by it's PK (mappedBy="editor") to Book
So in Book this is what we have to do (the inverse to OneToMany and define an Editor for each Book, so each child will have a reference to it's Dad):

The last thing is just declare which column & attribute will be used to do the JOIN between child and father


You can get more details if you look for that topic in Hibernate official documentation.
And these are my DAO's (I just included 1 as example), others should be similar. Always code oriented to interfaces! Later you'll thank me. In my next entry I will explain my Services and we'll be ready for using CXF.