Tuesday, April 17, 2012

LIARS among us - Ammar Afzal


Few months earlier I received a email with subject "Ammar Afzal, Hum Sharminda Hain" (Ammar Afzal, we are embarrassed) from a good colleague.

Email subject got my attention and when I opened the email, it had an image attachment with the content written in Urdu. This email was about a guy from Okara city of Pakistan, who is so talented and with out of the world abilities in him, that he resolved a critical issue in one of the most famous international bank.

The email states that Mr. Ammar Afzal is a OCP with outstanding performance in marks obtained. I wasn't able to digest it, so I googled him and found no such information as per the contents of email. On my queries on this from my colleagues, they were shocked and feeling sorry on forwarding the email without verification.

Today another colleague showed me a Video on YouTube, in which the same guy was interviewed by the National television channel. He was saying that he has got telephone call from Bill Gates, Yes Bill Gates and he is about to join Microsoft as Managing Director. I was so shocked and again after googling I found no information about that guy whatsoever.

I am so SURPRISED that in Pakistan anyone can get get in and throws any idiotic things from his mouth and we just air it without any authentication.

If you took a simple analysis of both the scenarios for correcting issue in Bank's ATM and being hired at Microsoft, even a 12 year old can come up with questions like this....

1) Does a Multinational bank provide their ATM's software code, server access, scripts to anyone for fixing a bug
2) A OCP with huge talent in DB got hired in Microsoft for OS Windows 9 development.
3) Their are only 49 developers in Microsoft and he is 49th but in terms of work he is # 1, that is just WOW and HOW ???.
4) Bill Gates is calling someone or may be every one who is being hired at Microsoft. (as Mr. Ammar Afzal quoted he got 6 minutes call from Bill Gates)
5) ..... I can go on with this so let everyone use their own imaginations.

Kindly find below some of the links and video I found about this guy named "Ammar Afzal"

The whole purpose of this post is to spread the information and keep others doing such kind









attention Pakistani Students - Fake story of Ammar Afzal

Ammar Afzal's Liar Blog

Another posting without Authentication

Ammar Afzal, we are proud of you, Mr. Liar








Monday, August 1, 2011

Apache Commons Exception -- Must issue a STARTTLS command first

While working on Apache Commons you may experience that email Client example provided at Apache's site may work in a simple java main method but denie to work on your web server (Tomcat).

Below is the example provided at http://commons.apache.org/email/userguide.html.


Email email = new SimpleEmail();
email.setHostName("smtp.gmail.com");
email.setSmtpPort(587);
email.setAuthenticator(new DefaultAuthenticator("username", "password"));
email.setTLS(true);
email.setFrom("user@gmail.com");
email.setSubject("TestMail");
email.setMsg("This is a test mail ... :-)");
email.addTo("foo@bar.com");
email.send();



You may experience the below error while executing this code in any web server like Tomcat.


DEBUG SMTP: connected to host "smtp.gmail.com", port: 25


RSET
250 2.1.5 Flushed e6sm6270355pbm.7
com.sun.mail.smtp.SMTPSendFailedException: 530 5.7.0 Must issue a STARTTLS command first. e6sm6270355pbm.7

        at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:1668)
        at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:1207)
        at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:735)
        at javax.mail.Transport.send(Transport.java:95)
        at javax.mail.Transport.send(Transport.java:48)
        at org.apache.commons.mail.Email.sendMimeMessage(Email.java:1232)
        at org.apache.commons.mail.Email.send(Email.java:1267)
        at org.artstor.adam.service.util.EmailClient.sendEmail(EmailClient.java:65)
        at org.artstor.adam.service.thread.ExportLaunchThread.sendEmails(ExportLaunchThread.java:248)
        at org.artstor.adam.service.thread.ExportLaunchThread.run(ExportLaunchThread.java:215)
        at org.artstor.adam.service.thread.ThreadPool$WorkerThread.run(ThreadPool.java:144)
QUIT
221 2.0.0 closing connection e6sm6270355pbm.7
DEBUG SMTP: useEhlo true, useAuth false


The main reason for this issue is that properties for port cannot be set properly for the client.
below change in code can save few minutes of your life.


            Email email = new SimpleEmail();
            email.setHostName("smtp.gmail.com");
            email.setSmtpPort(587);
            email.setAuthenticator(new DefaultAuthenticator("username", "password"));
            email.setTLS(true);
            email.setFrom("me@me.com");
            email.setSubject("some subject");
            email.setMsg("some message");
            email.setDebug(true);

            email.getMailSession().getProperties().put("mail.smtp.auth", "true");
            email.getMailSession().getProperties().put("mail.debug", "true");
            email.getMailSession().getProperties().put("mail.smtp.port""587");
            email.getMailSession().getProperties().put("mail.smtp.socketFactory.port""587");
            email.getMailSession().getProperties().put("mail.smtp.starttls.enable", "true");
            email.addTo("someone@mail.com");
            email.send();




I hope it helps.

Happy Coding



Thursday, July 21, 2011

How to rotate Tomcat catalina.out


If catalina.out becomes 2GB in size, tomcat crashes and fails to start without any error message. To avoid this scenario you should rotate catalina.out frequently. This article describes how to setup auto rotation of catalina.out on a linux/unix machine.

How to automatically rotate catalina.out daily or when it becomes bigger than 5M

1. Create this file
  1. /etc/logrotate.d/tomcat  
2. Copy the following contents into the above file
  1. /var/log/tomcat/catalina.out {  
  2.  copytruncate  
  3.  daily  
  4.  rotate 7  
  5.  compress  
  6.  missingok  
  7.  size 5M  
  8. }  
About the above configuration:
  • Make sure that the path /var/log/tomcat/catalina.out above is adjusted to point to your tomcat’s catalina.out
  • daily rotates the catalina.out daily
  • rotate – keeps at most 7 log files
  • compress – compresses the rotated files
  • size – rotates if the size of catalina.out is bigger than 5M
  • copytruncate – truncates the original log file in place after creating a copy, instead of moving the old log file and optionally creating a new one, It can be used when some program can not be told to close its logfile and thus might continue writing (appending) to the previous log file forever. Note that there is a very small time slice between copying the file and truncating it, so some logging data might be lost. When this option is used, the create option will have no effect, as the old log file stays in place.
You don’t need to do anything else.

How it works

  1. Every night the cron daemon runs jobs listed in the /etc/cron.daily/ directory
  2. This triggers the /etc/cron.daily/logrotate file which is generally shipped with linux installations. It runs the command “/usr/sbin/logrotate /etc/logrotate.conf
  3. The /etc/logrotate.conf includes all scripts in the /etc/logrotate.d/ directory.
  4. This triggers the /etc/logrotate.d/tomcat file that you wrote in the previous step.

Run logrotate manually

Run the following command to run the cron job manually
  1. /usr/sbin/logrotate /etc/logrotate.conf  

Is it completely safe?

See the description of copytruncate method above. There is a slight chance of a small amount of logging data loss between copy and truncate steps, usually it is acceptable but sometimes its not.

More logrotate options

To see all logrotate options on your system, see the manual:
  1. man logrotate  


References:
http://www.vineetmanohar.com/2010/03/howto-rotate-tomcat-catalina-out/

Sunday, February 20, 2011

Too Many Open Files Error And Solution


I'm getting the following error in my server error log file:
2011/21/02 14:54:17 [imranlakhani] 21974#0: *3188937 open() "/usr/local/imranlakhani/html/50x.html" failed (24: Too many open files), client: 88.x.y.z, server: example.com, request: "GET /file/images/background.jpg HTTP/1.1", upstream: "http://10.8.4.227:81//file/images/background.jpg", host: "example.com"
How do I fix this problem under CentOS / RHEL / Fedora Linux or UNIX like operating systems?
Linux / UNIX sets soft and hard limit for the number of file handles and open files. You can use ulimit command to view those limitations:
su - imran
To see the hard and soft values, issue the command as follows:
ulimit -Hn
ulimit -Sn

Increase Open FD Limit at Linux OS Level

Your operating system set limits on how many files can be opened by server. You can easily fix this problem by setting or increasing system open file limits under Linux. Edit file /etc/sysctl.conf, enter:
# vi /etc/sysctl.conf

To see the hard and soft values, issue the command as follows:
ulimit -Hn
ulimit -Sn

Increase Open FD Limit at Linux OS Level

Your operating system set limits on how many files can be opened by server. You can easily fix this problem by setting or increasing system open file limits under Linux. Edit file /etc/sysctl.conf, enter:
# vi /etc/sysctl.conf
Append / modify the following line:
fs.file-max = 70000
Save and close the file. Edit /etc/security/limits.conf, enter:
# vi /etc/security/limits.conf
Set soft and hard limit for all users or imran user as follows:
imran       soft    nofile   10000
imran       hard    nofile  30000
Save and close the file. Finally, reload the changes with sysctl command:
# sysctl -p

imran worker_rlimit_nofile Option (Increase Open FD Limit at imran Level)

Imran also comes with worker_rlimit_nofile directive which allows to enlarge this limit if it's not enough on fly at process level. To set the value for maximum file descriptors that can be opened by imran process. Edit imran.conf file, enter:
# vi /usr/local/imran/conf/imran.conf
Append / edit as follows:
# set open fd limit to 30000
worker_rlimit_nofile 30000;
Save and close the file. Reload imran web server, enter:
# /usr/local/imran/sbin/imran -t && /usr/local/imran/sbin/imran -s reload
# su - imran
$ ulimit -Hn
$ ulimit -Sn

Sample outputs:
30000
10000


Friday, February 18, 2011

Hibernate "inverse" mapping attribute - Understanding The Logic Engine

Generality
This page intends to give an internal view and understanding of inverse="true". Please, please, please read the Hibernate reference guide and especially:
  • Mapping a collection
  • Bidirectional Association
  • Parent Child Relationships
and the FAQs (the official ones and the one from the Wiki) before reading this.
Inverse defines which side is responsible of the association maintenance. The side having inverse="false" (default value) has this responsibility (and will create the appropriate SQL query - insert, update or delete). Changes made to the association on the side of the inverse="true" are not persisted in DB.
Inverse attribute is not related in any way to the navigation through relationship. It is related to the way hibernate generate SQL queries to update association data. Association data are:
  • a column in the one-to-many association
  • a row in the association table in a many-to-many association
Monodirectional association is managed by the only side available through navigation. When association is bidirectional, choosing the manager side allow better SQL optimization, this is the recommended behaviour.

one-to-many sample

Let's have a look at a simple one-to-many sample. Setting inverse="true" is recommanded and allow SQL optimization.
Note that <many-to-one> is always inverse="false" (the attribute does not exist).
<class name="net.sf.test.Parent" table="parent">
  <id name="id" column="id" type="long" unsaved-value="null">
    <generator class="sequence">
      <param name="sequence">SEQ_DEFAULT</param>
    </generator>
  </id>
  <set name="children" lazy="true" inverse="true">
      <key column="parent_id"/>
      <one-to-many class="net.sf.test.Child"/>
  </set>
</class>

<class name="net.sf.test.Child" table="child">
  <id name="id" column="id" type="long" unsaved-value="null">
    <generator class="sequence">
      <param name="sequence">SEQ_DEFAULT</param>
    </generator>
  </id>
  <many-to-one name="parent" column="parent_id" not-null="true"/>
</class>
The inverse="true" is set to the one side.

Proper code

Parent p = new Parent();
Child c = new Child();
p.setChildren(new HashSet());
p.getChildren().add(c);
c.setParent(p);

session.save(p);
session.save(c);
session.flush();
Will do the following SQL queries
Hibernate: select SEQ_DEFAULT.nextval from dual
Hibernate: select SEQ_DEFAULT.nextval from dual
Hibernate: insert into parent (id) values (?)
Hibernate: insert into child (parent_id, id) values (?, ?)
Hibernate insert parent then insert child. Note that my DB has a not null FK constraint on Child(parent_id), inserts work fine because I set <many-to-one not-null="true"
Note that I explicitly save parent and child objets. A better way is to use the cascade="save-update" element. I didn't do it to keep this explanation easier to understand and avoid concepts mismatch.

inverse="true" sample


Insert

Parent p = new Parent();
Child c = new Child();
p.setChildren(new HashSet());
p.getChildren().add(c);
c.setParent(p);

session.save(p);
session.flush(); //flush to DB
System.out.println("Parent saved");

session.save(c);
System.out.println("Child saved");
session.flush(); //flush to DB
Will do the following SQL queries
Hibernate: select SEQ_DEFAULT.nextval from dual
Hibernate: insert into parent (id) values (?)
Parent saved
Hibernate: select SEQ_DEFAULT.nextval from dual
Hibernate: insert into child (parent_id, id) values (?, ?)
Child saved
As you can see the relationship (incarnated by the parent_id column) is set during the child save : this is of the child responsibility. When saving parent, nothing is done on the relationship.

Update

Let's have a look at a relationship update
Parent p = (Parent) session.load(Parent.class, parentId);
Parent p2 = (Parent) session.load(Parent.class, parentId2);
        
c = (Child) session.find(
            "from Child as child where child.parent = ?",
            p, Hibernate.entity(Parent.class)).get(0);

// change parent of child c from p to p2
p.getChildren().remove(c);
p2.getChildren().add(c);
c.setParent(p2);
Will do the following SQL queries
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 1
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 2
Hibernate: select child0_.id as id, child0_.parent_id as parent_id from child child0_ where (child0_.parent_id=? ) //get children of parent 1

Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
//load childrens of Parent 1 and 2 (can't avoid this with set, see FAQ)

Hibernate: update child set parent_id=? where id=?
After a proper Java setting of the Parent child relationship (both side), Hibernate, set parent_id column to the proper value. As you can see, only 1 update is executed.
Now, we'll see inverse="true" in action ;-)
Parent p = (Parent) session.load(Parent.class, parentId);
Parent p2 = (Parent) session.load(Parent.class, parentId2);
        
c = (Child) session.find(
            "from Child as child where child.parent = ?",
            p, Hibernate.entity(Parent.class)).get(0);

c.setParent(p2);
Will do the following SQL queries
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 1
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 2
Hibernate: select child0_.id as id, child0_.parent_id as parent_id from child child0_ where (child0_.parent_id=? ) //get children 

Hibernate: update child set parent_id=? where id=?
The relationship is updated because I change it on the child side. Note that the object tree is not consistent with the Database (children collections are not up to date). This is not recommanded.
On the contrary,
Parent p = (Parent) session.load(Parent.class, parentId);
Parent p2 = (Parent) session.load(Parent.class, parentId2);
        
c = (Child) session.find(
            "from Child as child where child.parent = ?",
            p, Hibernate.entity(Parent.class)).get(0);

p.getChildren().remove(c);
p2.getChildren().add(p);
Will do the following SQL queries
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 1
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 2
Hibernate: select child0_.id as id, child0_.parent_id as parent_id from child child0_ where (child0_.parent_id=? ) //get children 

Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
//load childrens of Parent 1 and 2 (can't avoid this see FAQ)
Relationship update is not executed because update is only done on the parent side.

inverse="false"

inverse="false" (the default value) is not optimized for bidirectional relationships.
<class name="net.sf.test.Parent" table="parent">
  <id name="id" column="id" type="long" unsaved-value="null">
    <generator class="sequence">
      <param name="sequence">SEQ_DEFAULT</param>
    </generator>
  </id>
  <set name="children" lazy="true" inverse="false">
      <key column="parent_id"/>
      <one-to-many class="net.sf.test.Child"/>
  </set>
</class>

<class name="net.sf.test.Child" table="child">
  <id name="id" column="id" type="long" unsaved-value="null">
    <generator class="sequence">
      <param name="sequence">SEQ_DEFAULT</param>
    </generator>
  </id>
  <many-to-one name="parent" column="parent_id" not-null="true"/>
</class>
The inverse="false" is set to the one side.

insert

Parent p = new Parent();
Child c = new Child();
p.setChildren(new HashSet());
p.getChildren().add(c);
c.setParent(p);

session.save(p);
session.save(c);
session.flush();
Will do the following SQL queries
Hibernate: select SEQ_DEFAULT.nextval from dual
Hibernate: select SEQ_DEFAULT.nextval from dual
Hibernate: insert into parent (id) values (?)
Hibernate: insert into child (parent_id, id) values (?, ?)
Hibernate: update child set parent_id=? where id=?
Parent is responsible of the relationship. Hibernate insert parent, insert child then update the relationship (as a request to the parent). Two SQL orders are executed (one insert and one update) instead of one.
Note that I cannot do a flush between session.save(p) and session.save(c) because, parent, which is responsible of the relationship, needs a persistent child to play with.

update

Let's have a look at a relationship update
Parent p = (Parent) session.load(Parent.class, parentId);
Parent p2 = (Parent) session.load(Parent.class, parentId2);
        
c = (Child) session.find(
            "from Child as child where child.parent = ?",
            p, Hibernate.entity(Parent.class)).get(0);

p.getChildren().remove(c);
p2.getChildren().add(c);
c.setParent(p2);
Will do the following SQL queries
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=?    //get parent 1
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=?    //get parent 2
Hibernate: select child0_.id as id, child0_.parent_id as parent_id from child child0_ where (child0_.parent_id=? )
//get first child for parent 1

Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
//load childrens of Parent 1 and 2 (can't avoid this see FAQ)

Hibernate: update child set parent_id=? where id=?               // child.setParent
Hibernate: update child set parent_id=null where parent_id=?     //remove
Hibernate: update child set parent_id=? where id=?               // add
As you can see, having set inverse="true" allow the relationship to be managed by the parent side AND the child side. Several updates to the association data are done. This is inefficient considering the inverse="true" equivalent.
Parent p = (Parent) session.load(Parent.class, parentId);
Parent p2 = (Parent) session.load(Parent.class, parentId2);
        
c = (Child) session.find(
            "from Child as child where child.parent = ?",
            p, Hibernate.entity(Parent.class)).get(0);

p2.getChildren().add(c);
Will do the following SQL queries
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=?    //get parent 1
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=?    //get parent 2
Hibernate: select child0_.id as id, child0_.parent_id as parent_id from child child0_ where (child0_.parent_id=? )
//get first child for parent 1

Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
//load childrens of Parent 1 and 2 (can't avoid this see FAQ)

Hibernate: update child set parent_id=? where id=?               // add
The relationship is properly set but the object model is in inconsistent state. This is not recommanded.

Conclusion

Using and understanding inverse="true" is essential to optimize your code. Prefer using inverse="true" on bidirectional association. After this tutorial it will be soooo easy ;-)



Sunday, February 13, 2011

Hibernate inverse="true" - Understanding The Logic Engine


What is “inverse”?

This is the most confusing keyword in Hibernate, at least i took quite a long time to understand what is it. The “inverse” keyword is always declared in one-to-many and many-to-many relationship (many-to-one doesn’t has inverse keyword), It defines which side is responsible to take care of the relationship.

Always put inverse=”true” in your collection variable?

There are many Hibernate articles try to explain the “inverse” with many Hibernate “official” jargon, which is very hard to understand (at least to me). In few articles, they even suggested that just forget about what is “inverse”, and always put the inverse=”true” in the collection variable. This statement is always true – “put inverse=true in collection variable”, but do not blindfold on it, try to understand the reason behind is essential to optimal your Hibernate performance.

“inverse”, can it change to “relationship owner”?

In Hibernate, only the relationship owner should maintain the relationship, and the “inverse” keyword is created to defines which side is the owner to maintain the relationship. However the “inverse” keyword itself is not verbose enough, I would suggest change the keyword to “relationship_owner“. The inverse=”true” means this is the relationship owner, whereas inverse=”false” (default) means it’s not.
Let’s go though a quick example to grab a draft idea of “inverse”…

Preparing the data for demonstration…

1. Database tables

This is a one-to-many relationship table design, a STOCK table has many occurrences in STOCK_DAILY_RECORD table.


2. Hibernate implementation

Stock.java
public class Stock implements java.io.Serializable {
   ...
   private Set<StockDailyRecord> stockDailyRecords = 
                                  new HashSet<StockDailyRecord>(0);
   ...
StockDailyRecord.java
public class StockDailyRecord implements java.io.Serializable {
   ...
   private Stock stock;
   ...
Stock.hbm.xml
>
     name="com.mkyong.common.Stock" table="stock" ...>
    ...
     name="stockDailyRecords" table="stock_daily_record" fetch="select">
        >
             name="STOCK_ID" not-null="true" />
        >
         class="com.mkyong.common.StockDailyRecord" />
    >
    ...
StockDailyRecord.hbm.xml
>
   name="com.mkyong.common.StockDailyRecord" table="stock_daily_record" ...>
  ...
   name="stock" class="com.mkyong.common.Stock">
        name="STOCK_ID" not-null="true" />
  >
  ...

3. Question …

See this file – “Stock.hbm.xml“.
>
     name="com.mkyong.common.Stock" table="stock" ...>
    ...
     name="stockDailyRecords" table="stock_daily_record" fetch="select">
        >
             name="STOCK_ID" not-null="true" />
        >
         class="com.mkyong.common.StockDailyRecord" />
    >
    ...
If the Set variable (stockDailyRecords) in Stock object is modified, and save the Stock object like following
Stock stock = new Stock();
stock.getStockDailyRecords().add(stockDailyRecords);
session.save(stock);
Will it update the StockDailyRecord table?
Hibernate: 
    update mkyong.stock_daily_record 
    set STOCK_ID=? 
    where DAILY_RECORD_ID=?

4. Answer …

inverse” is controlling the above scenario, to define which side should maintain the relationship.
  • Inverse = false (default) – will execute “update mkyong.stock_daily_record” and update the relationship.
  • Inverse = true – Do nothing.
Got it? May be not, let’s explore more examples to understand about it.

“Inverse = false” example

If no “inverse” keyword is declared, the default is inverse = “false”, which is equal to

...
 name="stockDailyRecords" inverse="false" table="stock_daily_record" ...>
It means both sides are the owner of the relationship. In Hibernate, it will ask both sides to update the foreign key “stock_daily_record.STOCK_ID” in “StockDailyRecord” table.
  • Stock will update the foreign key “stock_daily_record.STOCK_ID” if Set variable (stockDailyRecords) is modified.
  • StockDailyRecord will update the foreign key “stock_daily_record.STOCK_ID” with Stock property as well.

1. Insert example …

Here’s an insert example for inverse=”false”, when a Stock object is saved, Hibernate will generated two SQLSta, one insert and one update.
Stock stock = new Stock();
stock.getStockDailyRecords().add(stockDailyRecords);
session.save(stock);
Output
Hibernate: 
    insert into mkyong.stock (STOCK_CODE, STOCK_NAME) 
    values (?, ?)
...
Hibernate: 
    update mkyong.stock_daily_record 
    set STOCK_ID=? 
    where DAILY_RECORD_ID=?
Stock will update the “stock_daily_record.STOCK_ID” through Set variable (stockDailyRecords), because Stock is the relationship owner.

2. Update example …

Here’s an update example for inverse=”false”, Hibernate will generated three SQL statements, one insert and two updates.
        Query q = session.createQuery("from Stock where stockCode = :stockCode ");
        q.setParameter("stockCode", "4715");
        Stock stock = (Stock)q.list().get(0);
        stock.setStockName("GENM1");
 
        StockDailyRecord stockDailyRecords = new StockDailyRecord();
        //set stockDailyRecords data
 
        stockDailyRecords.setStock(stock);        
        stock.getStockDailyRecords().add(stockDailyRecords);
 
        session.save(stockDailyRecords);
        session.update(stock);
Output
Hibernate: 
    insert into mkyong.stock_daily_record (STOCK_ID, ...) 
    values (?, ...)
 
Hibernate: 
    update mkyong.stock 
    set STOCK_CODE=?, STOCK_NAME=? 
    where STOCK_ID=?
 
Hibernate: 
    update mkyong.stock_daily_record 
    set STOCK_ID=? 
    where DAILY_RECORD_ID=?
Stock will update the “stock_daily_record.STOCK_ID” through Set variable (stockDailyRecords), because Stock is the relationship owner.
Note
Wait…do you think the third update statement is necessary? The inverse = “true” in Set variable (stockDailyRecords) can stop the Hibernate to generate the unnecessary third update statement.

inverse = “true” example

The inverse=”true” is declared at the Set variable (stockDailyRecords), which means Stock is not the relationship owner, the owner is belong to StockDailyRecord class. In Hibernate, it will enable only the StockDailyRecord class to update the foreign key “stock_daily_record.STOCK_ID” in StockDailyRecord table.

 name="stockDailyRecords" inverse="true" table="stock_daily_record" ...>
  • Stock will not update the foreign key “stock_daily_record.STOCK_ID” if Set variable (stockDailyRecords) is modified.
  • Only StockDailyRecord will update the foreign key “stock_daily_record.STOCK_ID” with Stock property.

1. Insert example …

Here’s an insert example for inverse=”true”, when a Stock object is saved, Hibernate will generated one insert SQL statement.
Stock stock = new Stock();
stock.getStockDailyRecords().add(stockDailyRecords);
session.save(stock);
Output
Hibernate: 
    insert into mkyong.stock (STOCK_CODE, STOCK_NAME) 
    values (?, ?)
Since “Stock” is not the owner of the relationship, it will not update the “stock_daily_record.STOCK_ID” in StockDailyRecord table.

2. Update example …

Here’s an update example for inverse=”true”, Hibernate will generated two SQL statements, one insert and one update.
        Query q = session.createQuery("from Stock where stockCode = :stockCode ");
        q.setParameter("stockCode", "4715");
        Stock stock = (Stock)q.list().get(0);
        stock.setStockName("GENM1");
 
        StockDailyRecord stockDailyRecords = new StockDailyRecord();
        //set stockDailyRecords data
 
        stockDailyRecords.setStock(stock);        
        stock.getStockDailyRecords().add(stockDailyRecords);
 
        session.save(stockDailyRecords);
        session.update(stock);
Output
Hibernate: 
    insert into mkyong.stock_daily_record (STOCK_ID, ...) 
    values (?, ...)
 
Hibernate: 
    update mkyong.stock 
    set STOCK_CODE=?, STOCK_NAME=? 
    where STOCK_ID=?
Since “Stock” is not the owner of the relationship, it will not update the “stock_daily_record.STOCK_ID” in stockDailyRecord table.
inverse vs cascade
Many people like to compare between inverse and cascade, but both are totally different notions, see the differencial here.

Conclusion

Understanding the “inverse” is essential to optimize your Hibernate code, it helps to avoid many unnecessary update statements, which mention in the “update example for inverse=false” above. At last, try to remember the inverse=”true” mean this is the relationship owner to handle the relationship.

Reference

  1. http://www.mkyong.com/hibernate/inverse-true-example-and-explanation/
  2. http://simoes.org/docs/hibernate-2.1/155.html
  3. http://docs.jboss.org/hibernate/stable/core/reference/en/html/example-parentchild.html
  4. http://tadtech.blogspot.com/2007/02/hibernate-when-is-inversetrue-and-when.html