Thursday, August 27, 2015

Create Simple Project with Hibernate + Maven

I have another with referring to mkyoung examples with  hibernate
http://cgenit.blogspot.com/2014/05/creating-hibernate-projects.html

but this is in brief
Here I use eclipse IDE and with Maven plugin

1. Create Maven project using maven plugin in  eclipse.
2. Hibernate is ORM tool. we need database table and Java class to map table .
3. As first we add hibernate dependency. We need to add hibernate dependencies

========================================

<!-- Hibernate framework -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.0.0.Final</version>
</dependency>

========================================
 4. Hibernate configuration file(hibernate.cfg.xml) - we need to config data base. we use MySql. we do this using hibernate configuration file
========================================

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>

<!-- Assume hibernateBasic is the database name -->
<property name="hibernate.connection.url">
jdbc:mysql://localhost/hibernateBasic
</property>
<property name="hibernate.connection.username">
root
</property>
<property name="hibernate.connection.password">
root123
</property>
<!-- JDBC connectiopn pool (use built in) -->
<property name="connection.pool_size">1</property>
<!-- drop and recreate the database schema on startup -->
<property name="hbmtoddl.auto">create</property>

</session-factory>
</hibernate-configuration>


========================================



5. As we use Mysql we need to add the dependency jar for mysql connector
========================================

                <!-- MySQL database driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>

========================================
 6. Now we create the Model or dto class, UserDetail

=================================================================
package hibernate.basic.dto;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class UserDetails {

@Id
private int userId;
private String userName;

public int getUserId() {
return userId;
}

public void setUserId(int userId) {
this.userId = userId;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

}


==================================================================

7. annotate with @Entity - we need to tell  dto is and entity class map to table
 @Id = map the id - USe "javax.persistence"  annotation over hibernate annotation

8. we need to add the annotated class to configuration

                 <!-- Names the annotated entity class -->
<mapping class="hibernate.basic.dto.UserDetails"/>

9. Now to save the dto -
 Create Session factory - singleton, configurations for database. "hibernate.cfg.xml" file has details using this configurations we create Session Factory
Using Session factory , we create sessions -

======================================================================

package hibernate.basic.main;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import hibernate.basic.dto.UserDetails;

public class HibernateTest {
public static void main(String[] args) {

// set up user object
UserDetails userDetails = new UserDetails();
userDetails.setUserId(1);
userDetails.setUserName("kamal");

// now save object
// config the database. once configure, we build the Session Factory
SessionFactory sessionFactory = new Configuration().configure()
.buildSessionFactory();

// create session using Session factory
Session session = sessionFactory.openSession();

// before save, we create transaction
// transaction create single unit of work
session.beginTransaction();
session.save(userDetails);

// once save end transaction using commit
session.getTransaction().commit();

session.close();

}
}

======================================================================

As we are using property "property name="hibernate.hbm2ddl.auto"" as "create"
this will create the database scheme every time transaction happens


If you need the final configuration of , we are not using xml mapping

======================================================================
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>

<!-- Assume hibernateBasic is the database name -->
<property name="hibernate.connection.url">
jdbc:mysql://localhost/hibernateBasic
</property>
<property name="hibernate.connection.username">
root
</property>
<property name="hibernate.connection.password">
root123
</property>
<!-- JDBC connectiopn pool (use built in) -->
<property name="connection.pool_size">1</property>
<!-- drop and recreate the database schema on startup -->
<property name="hibernate.hbm2ddl.auto">create</property>
<property name="hibernate.show_sql">true</property>


<!-- List of XML mapping files -->
<!-- <mapping resource="Employee.hbm.xml" /> -->

<!-- Names the annotated entity class -->
<mapping class="hibernate.basic.dto.UserDetails" />

</session-factory>
</hibernate-configuration>

======================================================================



output of the program
=====================================================================
INFO: HHH000227: Running hbm2ddl schema export
Hibernate: drop table if exists UserDetails
Hibernate: create table UserDetails (userId integer not null, userName varchar(255), primary key (userId))
Aug ********* PM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000230: Schema export complete
Hibernate: insert into UserDetails (userName, userId) values (?, ?)
Hibernate: update UserDetails set userName=? where userId=?

=====================================================================

Summary
1. create maven project
2. add maven dependency for hibernate and Mysql connector
3. config database for hibernate - hibernate.cfg.xml , put it in resources
4. create model class  and map using annotation "javax.persistence"  @Entity and @Id
5. put the annotated model class to hibernate configuration file
6. to save . Create Session factory using the given configuration in hibernate.cfg.xml.
 Use the Session factory to create session.
 Open session and begin transaction - to create single unit of work
 commit and close session


Note : we have used "hbm2ddl" property "create" , where this will create brand new fresh table every time transaction executes.

If you need to few things

1. Let's add two objects

============================================================
// set up user object
UserDetails userDetails = new UserDetails();
userDetails.setUserId(1);
userDetails.setUserName("kamal");

UserDetails userDetails2 = new UserDetails();
userDetails2.setUserId(2);
userDetails2.setUserName("kamal2");

                  // now save object
// config the database. once configure, we build the Session Factory
SessionFactory sessionFactory = new Configuration().configure()
.buildSessionFactory();

// create session using Session factory
Session session = sessionFactory.openSession();

// before save, we create transaction
// transaction create single unit of work
session.beginTransaction();
session.save(userDetails);
session.save(userDetails);
session.save(userDetails2);

// once save end transaction using commit
session.getTransaction().commit();

session.close();

=======================================================
 
Output
=======================================================
# userId, userName
'1', 'kamal'
'2', 'kamal2'

=======================================================

This has no big deal as this will add two entries

output of eclipse will be as below. you can see two insert entries

============================================================
Hibernate: drop table if exists UserDetails
Hibernate: create table UserDetails (userId integer not null, userName varchar(255), primary key (userId))
********* PM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000230: Schema export complete
Hibernate: insert into UserDetails (userName, userId) values (?, ?)
Hibernate: insert into UserDetails (userName, userId) values (?, ?)

=======================================================================

2. Now let's change the name or change the value of a model object and see what will happen

============================================================
// set up user object
UserDetails userDetails = new UserDetails();
userDetails.setUserId(1);
userDetails.setUserName("kamal");



// now save object
// config the database. once configure, we build the Session Factory
SessionFactory sessionFactory = new Configuration().configure()
.buildSessionFactory();

// create session using Session factory
Session session = sessionFactory.openSession();

// before save, we create transaction
// transaction create single unit of work
session.beginTransaction();
session.save(userDetails);
userDetails.setUserName("name2");
session.save(userDetails);


// once save end transaction using commit
session.getTransaction().commit();

session.close();

============================================================

Output
=======================================================
# userId, userName
'1', 'name2'


=======================================================

Note : you can see the final value has been change. That is because we are using same object and we changing the values of the same reference object before commit.
Note : Before commit.

Also if you look at the eclipse output, you can see the insert and update both statements. So now you may have a problem of session level cache.

why hibernate does make insert and update ?? why not in one single db call ??


eclipse output
=======================================================
Hibernate: drop table if exists UserDetails
Hibernate: create table UserDetails (userId integer not null, userName varchar(255), primary key (userId))
Aug************* PM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000230: Schema export complete
Hibernate: insert into UserDetails (userName, userId) values (?, ?)
Hibernate: update UserDetails set userName=? where userId=?
=======================================================

3. Now let's comment the save of  the first model object and save the second object and see what will happen.

============================================================

// set up user object
UserDetails userDetails = new UserDetails();
userDetails.setUserId(1);
userDetails.setUserName("kamal");

UserDetails userDetails2 = new UserDetails();
userDetails2.setUserId(2);
userDetails2.setUserName("kamal2");

// now save object
// config the database. once configure, we build the Session Factory
SessionFactory sessionFactory = new Configuration().configure()
.buildSessionFactory();

// create session using Session factory
Session session = sessionFactory.openSession();

// before save, we create transaction
// transaction create single unit of work
session.beginTransaction();
session.save(userDetails);
userDetails.setUserName("name2");
// session.save(userDetails);
session.save(userDetails2);

// once save end transaction using commit
session.getTransaction().commit();

session.close();
============================================================


eclipse output
============================================================
Hibernate: drop table if exists UserDetails
Hibernate: create table UserDetails (userId integer not null, userName varchar(255), primary key (userId))
Aug ********* PM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000230: Schema export complete
Hibernate: insert into UserDetails (userName, userId) values (?, ?)
Hibernate: insert into UserDetails (userName, userId) values (?, ?)
Hibernate: update UserDetails set userName=? where userId=?
============================================================

db output
============================================================
# userId, userName
'1', 'name2'
'2', 'kamal2'

============================================================

OOOhhh , it's still adding the value to the database and you can see the both insert and update statement execution flow in the eclipse output.

Whether we call save it or not, the object will be saved with the initial state ("insert  statement") and the update of the state change, update name. All will be saved or persist to data base.

Note: In all above cases, we change the value of the first model object after saving it or after persist. So the once it's persist - the changes are persist in the database as you see.
Also two transations - Insert and Update.

If you do the change of state before save or persist(), then there will be only one insert command to the database. This is the answer for the what is happening with the session level cache.


You will understand more with the hibernate object states and difference between method save() and persist() and update() and dirty checking concepts.

***

Saving without Hibernate
1. we need JDBC Database configuration
2. The model object or POJO class
3. Service method to create a model object
4. Database design
5. DAO methods to save the object using SQL queries



With Hibernate
1. Hibernate Configuration  - JDBC Database configuration
2. Annotation (prevously we have xml mapping file hbm)  -  model object
3. Use Hibernate API - Service method to create a model object
4. Database deign -  Not needed
5. Dao Method - Not needed