Hibernate JPA with Oracle on Eclipse

jpa hibernate tutorialIn the previous article, we have gone through the concepts of Java Persistence API (JPA hence forth). In this article, let us try to build an Hibernate JPA example with Oracle database on Eclipse, which will show us a working model of everything we have learned so far. I am choosing the most common technologies for this – Hibernate, JPA, Oracle and Eclipse. Let us run it using the main method. This code should give you a start to try further complex concepts of JPA. In this example, let us not have any functional complexities, and try a plain insert and commit operation in a database table. Following steps need to be followed.

Steps To Build Hibernate JPA Example:

  • Database Set Up
  • Eclipse Project Set Up
  • Libraries
  • Java Code
  • Configuration
  • Running the Example
  • Troubleshooting

Database Set Up:

We are going to use Oracle (above version 9) database. Create two database entities using following script.

CREATE TABLE TAB_CUSTOMER
(
  CUSTOMER_ID  NUMBER(10) NOT NULL,
  CUSTOMER_NAME VARCHAR2(255)
)

CREATE SEQUENCE TAB_CUSTOMER_SEQ
  START WITH 1
  MAXVALUE 999999999999999999999999999
  MINVALUE 1
  NOCYCLE
  CACHE 20
  NOORDER;

Eclipse Project Set Up:

We are going to use dynamic web project. (There are options of using plain Java project or JPA project, but I am expecting it to help you to build a web application based on this.). Go through following screens to create JPAHibernateTutorial project.

Hibernate JPA Tutorial

Hibernate JPA Tutorial

Now the project is ready and we can add libraries and code to it.

Add Libraries:

We need following libraries in class path. Add these to /WEB-INF/lib directory.

asm.jar

commons-collections-3.1.jar

dom4j-1.6.1.jar

ejb3-persistence.jar

hibernate3.jar

hibernate-annotations.jar

hibernate-commons-annotations.jar

hibernate-core.jar

hibernate-entitymanager.jar

javassist-3.4.GA.jar

jta-1.1.jar

log4j.jar

ojdbc14.jar

slf4j-api-1.5.2.jar

slf4j-log4j12.jar

Java Code:

We have two java classes. One is the annotated Customer.java POJO. This maps to the table TAB_CUSTOMER. We are using sequence created above to generate the primary key. Second is the CustomerDAO.java. This class does the persistence work for us. It creates entity manager factory and entity manager defined in the configuration file, and saves the customer object in a transaction.

/src/main/java/Customer.java

import java.io.Serializable;

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

@SequenceGenerator(
	    name="SEQ_CUST",
	    sequenceName="TAB_CUSTOMER_SEQ"
	)

@Entity
@Table(name="TAB_CUSTOMER")
public class Customer implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_CUST")
    @Column(name="CUSTOMER_ID", precision=0)
    private Long customerId = null;

    @Column(name="CUSTOMER_NAME")
    private String customerName;

    public Long getCustomerId() {
		return customerId;
	}

	public void setCustomerId(Long customerId) {
		this.customerId = customerId;
	}

	public String getCustomerName() {
		return customerName;
	}

	public void setCustomerName(String aCustomerName) {
		this.customerName = aCustomerName;
	}

	public static long getSerialVersionUID() {
		return serialVersionUID;
	}

	public boolean equals(Object candidate) {
        if (candidate == this) {
            return true;
        }
        if (candidate instanceof Customer) {
            if ((this.getCustomerName() != null && ((Customer)candidate).getCustomerName() != null)) {
            	return (this.getCustomerId()==(((Customer)candidate).getCustomerId())&&
                 this.getCustomerName().equals(((Customer)candidate).getCustomerName()));
            }
        }
        return false;
    }

     public int hashCode() {
    	 return this.getCustomerId().intValue();
    }

}

/src/main/java/CustomerDAO.java

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class CustomerDAO {
    public Customer create(Customer newCustomer) {
    	EntityManagerFactory emf =
    		Persistence.createEntityManagerFactory("customerManager");
    	EntityManager em = emf.createEntityManager();
    	em.getTransaction().begin();
    	em.persist(newCustomer);
    	em.getTransaction().commit();
    	return newCustomer;
    }

    public static void main(String[] args){
    	Customer customer = new Customer();
    	customer.setCustomerName("Hibernate JPA Customer");
    	System.out.println("Customer id before creation:"
    			+ customer.getCustomerId());
    	CustomerDAO customerDAO = new CustomerDAO();
    	Customer persistedCustomer = customerDAO.create(customer);
    	System.out.println("Customer id after creation:"
    			+ persistedCustomer.getCustomerId());
    }
}

Configuration:

The heart of our JPA with hibernate example is the persistence.xml file. This holds the entity manager configuration along with database connection details. We are also specifying the annotated class Customer in this file. (Make sure you enter your own Oracle connection details here.) Actually, this file can be kept in the WEB-INF/META-INF/ directory. But we are keeping it in /src/resources/META-INF/ directory. Mind you, hibernate does not search for persistence.xml, but it searches for META-INF/persistence.xml. Hence we need to add ‘resources’ folder to class path and not META-INF.

/src/resources/META-INF/persistence.xml

org.hibernate.ejb.HibernatePersistence
      Customer

Adding resources to class path –

Hibernate JPA Tutorial

Second configuration we are using is the log4j.properties. We want everything to be printed on console, hence the log level is kept at TRACE. This will be automatically included in class path, as we have resources folder already included. Ensure the file path is correct.

/src/resources/log4j.properties

log4j.rootLogger=TRACE, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

log4j.appender.stdout=org.apache.log4j.RollingFileAppender
log4j.appender.stdout.File=D:/logs/JPAHibernateTutorial.log

log4j.appender.stdout.MaxFileSize=10MB
# Keep one backup file
log4j.appender.stdout.MaxBackupIndex=1

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%p %t %c - %m%n

Running the Hibernate JPA Example:

Finally, to see everything working, we run the main method of CustomerDAO class and see the log printed on console.

Troubleshooting:

While searching on internet, I found many questions around following exception. I also ended up in same, while trying to run the example. There are suggestions around, adding jars, adding persistence.xml in class path. This may solve your problem, but, I would reckon to first know the problem. In above example, we are having the log4j.properties file in class path and the log level set to TRACE. This will help you to know the exact problem.  It will print the error in log file specified.

Exception in thread “main” javax.persistence.PersistenceException: No Persistence provider for EntityManager named …..

4 Comments

  1. There are some things i could note by reading the code quickly:

    1) Using the customerId is bad idea for HasCode and Equals, since that is dependent on the DB Sequence Itself.

    Imagine an scenario where you want to store this Non Persisted object in a SET to collect them before saving into the DB (as OneTOMany Relation), it will throws NPE since the Id is not populated at that time.

    In Hibernate Site they talk about that.

    2) EntityManagerFactory emf =
    Persistence.createEntityManagerFactory

    Should be factor out into an its own initializer since this a very heavy operation and should be done only once.

    I probably understand this could be just a quick POC, but it definitely needs to be re-worked.

    Cheers!

  2. Hi, I ran the example and noticed the customer_id was incremented by every 50 (e.g. 100, 150, 200, 250…). However, if I ran a sql insert statement directly using SQLDeveloper, then the customer_id was incremented by 1. Why?

Leave a Reply

Your email address will not be published.


*