Scaffold your ideas into application
Get your free alpha access now.
Only 445 left, Hurry!
22 Aug 2016

Hibernate Tutorial Basic

This is the fifth part of J2EE beginner series and in this post we would add Hibernate ORM to the application which we have been developing for a while now. Please take some time to read earlier parts

  1. What is a server?
  2. Servlets
  3. JSP
  4. JDBC

To get started we would need the code base of the application we have been developing through this series. If you have not been following us, you can download the pre built source or clone it from github and checkout branch jdbc.

We would begin by adding hibernate dependency to our pom.xml

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>4.3.2.Final</version>
    </dependency>

One we have added this to pom, we need to refresh our eclipse project by running command mvn eclipse:eclipse and refreshing the project.

Hibernate is an Object Relational Mapping tool which helps bridge the Object Relational Mismatch, the purpose of ORM is to provide an Object based abstraction to underlying database, so we as user can behave as if there is no mismatch and underlying data store can understand OOP domain model. This paradigm would allow us to write a more domain driven design approach rather than SQL query based approach.

Lets begin by writing a User class to hold our data for user, for this example we will keep it very simple with minimal attributes but in real world you may have much more data.

User.java

    package com.scaffoldthis.model;

    public class User {

        private String userName;

        private String password;

    }

Now we need to tell Hibernate how to map this to database, for this we can use either XML mapping or Annotation based mapping, I prefer annotation based mapping as it is cleaner and has more features than xml based mapping, so we would be using annotations in this article. If you prefer xml, please comment to let us know. Lets go ahead and add our mappings.

User.java

    package com.scaffoldthis.model;

    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.Table;

    @Table(name = "app_user")
    @Entity
    public class User {

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "user_id")
        private Long userId;

        @Column(name = "user_name")
        private String userName;

        @Column(name = "password")
        private String password;

    }

Lets analyse all the annotations one by one. Every mapped class should have a @Entity annotation, this tells hibernate that it is a mapped entity, you can optionally provide the name for entity. @Table annotation is an optional annotation which tells hibernate which table maps to which entity, if we remove the @Table annotation, hibernate would generate a default table name based on NamingStrategy and try to map it to that table, for example in this case it would look for a table called User but our table is called app_user we need to tell hibernate to use this table name instead of default one. @Column annotation does the similar thing on field, which is also an optional annotation.

@Id annotation is for telling hibernate that the column is a primary key, @GeneratedValue is an annotation to tell hibernate that the column is a auto generated column and depending on the strategy of generation, the value would be generated. Since we are using MySQL, our default strategy is Identity, you can leave it to AUTO and hibernate would make the right choice for you.

Now that we have mapped the entity, we need to do some basic hibernate setup to let hibernate know where to find the stuff. For this we would create a HibernateUtil class, which would have all the configuration related to Hibernate.

     package com.scaffoldthis.dao;

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

    public class HibernateUtil {

        private static SessionFactory sessionFactory;

        public static void setup() {
            if (sessionFactory == null) {
                // A SessionFactory is set up once for an application
                sessionFactory = new Configuration().configure().buildSessionFactory();
            }
        }

        public static Session getSession() {
            setup();
            Session openSession = sessionFactory.openSession();
            return openSession;
        }

    }

This code expects a file hibernate.cfg.xml to be somewhere in classpath which holds the configurations like what database are we using and whats the URL, username and passwords. If we need to change the name of the file from hibernate.cfg.xml for whatever reasons then we need to supply the new name in configure(newname.xml)

This code would create a new session every time it is called, pretty much like the JDBC code which we had written in earlier article. We would look into optimising this later when we discuss transactions and isolation levels of transaction in one of the later articles.

Lets look at our hibernate.cfg.xml

    <?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>

            <property name="hibernate.connection.url">
                jdbc:mysql://localhost:3306/my_app
            </property>
            <property name="hibernate.connection.username">
                root
            </property>
            <property name="hibernate.connection.password">
                root
            </property>

            <mapping class="com.scaffoldthis.model.User"/>
        </session-factory>
    </hibernate-configuration>

I like to keep all the non java resources in src/main/resources folder, so this file goes there. This file contains the URL, username and passwors like our jdbc code, a few additional things in this file is the Dialect, which is a way to tell hibernate which database are we using, using this dialect, hibernate would generate appropriate queries for us. Note that we added our class definition at the bottom using mapping tag, any class which is mapped by hibernate should be added here.

Now we need to write a DAO for hibernate similar to our UserDao in last article, lets call this UserHibernateDao, this would have the same methods as UserDao so that we do not have to change lot of code in our servlet, however it would have been nice to create an interface to enforce that both our Dao follow the same method and signature. We would discuss more on this when we talk about Spring and Dependency Management in another article.

UserHibernateDao.java

    package com.scaffoldthis.dao;

    import java.util.List;

    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.hibernate.Transaction;

    import com.scaffoldthis.model.User;

    public class UserHibernateDao {

        public void createUser(String username, String password) {
            Session session = HibernateUtil.getSession();
            Transaction txn = session.beginTransaction();
            try {
                User user = new User();
                user.setUserName(username);
                user.setPassword(password);
                session.save(user);
                txn.commit();
            } catch (Exception e) {
                txn.rollback();
            } finally {
                session.close();
            }
        }

        public boolean isValidUser(String username, String password) {
            Session session = HibernateUtil.getSession();
            Transaction txn = session.beginTransaction();
            try {
                Query query = session.createQuery("from User u where u.userName = :name and u.password = :pwd");
                query.setParameter("name", username);
                query.setParameter("pwd", password);
                List list = query.list();
                if (list.isEmpty()) {
                    return false;
                }
                if (list.size() == 1) {
                    return true;
                }
                return false;
            } finally {
                txn.commit();
                session.close();
            }
        }
    }

Lets break down the code and understand what is going on.

    Session session = HibernateUtil.getSession();

This would create a new session, which is like a jdbc connection . In JDBC we would use the connection object for transaction as well as opening and closing connections, however in hibernate, we need a create a separate transaction object and use that for controlling transaction boundaries.

    Transaction txn = session.beginTransaction();
    txn.commit();
    txn.rollback();

Once we have a transaction object, we can commit or rollback using above code, similar to JDBC.

    session.save(user);

save method saves a new Object to the database, the object being passed should be the one which we mapped using annotations. If we want to update the object we would need to call session.update(user) or a safer way is to use session.saveOrUpdate(user) this way hibernate would determine whether to call an update or insert, in very simple terms, if the id attribute is null, then hibernate thinks it is a new object and would try to insert while if id property is there hibernate would try to update.

    Query query = session.createQuery("from User u where u.userName = :name and u.password = :pwd");

This code looks very similar to our PreparedStmt code from last article

    stmt = connection.prepareStatement("select * from app_user where user_name = ? and password = ?");

notice the difference is that we are using Java object names and property names instead of actual table names, the first query is in HQL (Hibernate Query Language) while the second query in plain SQL. Since hibernate knows what are our table names and column names, we can talk to hibernate in object terminology and hibernate would translate that to appropriate sql.

Now we need to only substitute our UserDao references from both CreateUserServlet.java and DemoServlet.java and we are ready to run our hibernate code.

In next article of the series, we would replace our servlets with Spring MVC code.


Stats:
186 views
Scaffold your ideas into application
Get your free alpha access now.
Only 445 left, Hurry!

Angular Directives Demystified

Directives are the most misunderstood aspect of angular JS. Learn how directives can help you keep your code clean.

Third wave of digital transformation

Third wave of digital transformation

Angularjs Tutorial: Understanding Scope

Scopes are one of the most important and rarely understood concept in angular, in this part we explore how scope works in angularjs.

Comments:

Leave your comments