Close

Spring ORM - Implementing DAO in JPA based application

[Last Updated: Nov 23, 2017]

This examples shows how to apply DAO pattern in JPA based Spring application. We are going to use Hibernate as a JPA provider. We are also going to use LocalEntityManagerFactoryBean to load EntityManagerFactory (see last example).

Example

A Generic Dao Interface

public interface Dao<T> {
    void save(T t);
    T load(long id);
    void delete(long id);
    void update(T t);
    List<T> loadAll();
}

A JPA Entity

@Entity
public class Person {
    @Id
    @GeneratedValue
    private long id;
    private String firstName;
    private String lastName;
    private String address;
    .............
}

The DAO implementation

package com.logicbig.example;

import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import java.util.List;

@Repository
public class PersonDaoJpaImpl implements Dao<Person> {

    @PersistenceUnit
    private EntityManagerFactory emf;

    @Override
    public void save(Person person) {
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        em.persist(person);
        em.getTransaction().commit();
        em.close();
    }

    @Override
    public Person load(long id) {
        EntityManager em = emf.createEntityManager();
        Person person = em.find(Person.class, id);
        em.close();
        return person;
    }

    @Override
    public void delete(long id) {
        EntityManager em = emf.createEntityManager();
        Person employee = em.find(Person.class, id);

        em.getTransaction().begin();
        em.remove(employee);
        em.getTransaction().commit();
        em.close();
    }

    @Override
    public void update(Person person) {

        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        em.merge(person);
        em.getTransaction().commit();
        em.close();
    }

    @Override
    public List<Person> loadAll() {
        EntityManager em = emf.createEntityManager();
        List<Person> persons = em.createQuery("Select t from Person t")
                                 .getResultList();
        em.close();
        return persons;
    }
}

Note that, we used JPA's @PersistenceUnit annotation on EntityManagerFactory. In Spring application PersistenceAnnotationBeanPostProcessor (implicitly activated with Spring's Java Config) is responsible to process @PersistenceContext and @PersistenceUnit annotations.

The Service Layer

@Service
public class PersonService {
    @Autowired
    private Dao<Person> dao;

    public void savePerson(Person person) {
        try {
            dao.save(person);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
    }

    public List<Person> getAllPersons() {
        try {
            return dao.loadAll();
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    public Person getPersonById(long id) {
        try {
            return dao.load(id);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void deletePerson(long id) {
        try {
            dao.delete(id);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
    }

    public void updatePerson(Person person) {
        try {
            dao.update(person);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
    }
}

The Example Client

@Component
public class ExampleClientBean {

    @Autowired
    PersonService personService;

    public void run() {
        System.out.println("'Persisting persons'");
        Person person = Person.create("Dana", "Whitley", "464 Gorsuch Drive");
        personService.savePerson(person);

        person = Person.create("Robin", "Cash", "64 Zella Park");
        personService.savePerson(person);

        List<Person> allPersons = personService.getAllPersons();
        System.out.println("Persons loaded: " + allPersons);

        person = personService.getPersonById(2);
        System.out.println("Person loaded by id : " + person);

        System.out.println("'updating person address with id 2'");
        person.setAddress("111 Yellow Hill");
        personService.updatePerson(person);

        System.out.println("'Deleting person by id 1'");
        personService.deletePerson(1);

        allPersons = personService.getAllPersons();
        System.out.println("Persons loaded: " + allPersons);
    }
}

Java Config and main class

package com.logicbig.example;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.LocalEntityManagerFactoryBean;

@Configuration
@ComponentScan
public class AppConfig {

    @Bean
    public LocalEntityManagerFactoryBean entityManagerFactoryBean() {
        LocalEntityManagerFactoryBean factory = new LocalEntityManagerFactoryBean();
        factory.setPersistenceUnitName("example-unit");
        return factory;
    }

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(AppConfig.class);
        context.getBean(ExampleClientBean.class).run();

        context.getBean(LocalEntityManagerFactoryBean.class).destroy();
    }
}

Output

'Persisting persons'
 Persons loaded: [Person{id=1, firstName='Dana', lastName='Whitley', address='464 Gorsuch Drive'}, Person{id=2, firstName='Robin', lastName='Cash', address='64 Zella Park'}]
 Person loaded by id : Person{id=2, firstName='Robin', lastName='Cash', address='64 Zella Park'}
'updating person address with id 2'
'Deleting person by id 1'
 Persons loaded: [Person{id=2, firstName='Robin', lastName='Cash', address='111 Yellow Hill'}]

Example Project

Dependencies and Technologies Used:

  • spring-context 5.0.1.RELEASE: Spring Context.
  • spring-orm 5.0.1.RELEASE: Spring Object/Relational Mapping.
  • hibernate-core 5.2.12.Final: The core O/RM functionality as provided by Hibernate.
    Implements javax.persistence:javax.persistence-api version 2.1
  • h2 1.4.196: H2 Database Engine.
  • JDK 1.8
  • Maven 3.3.9

Spring JPA DAO pattern Select All Download
  • spring-jpa-dao-example
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • PersonDaoJpaImpl.java
          • resources
            • META-INF

    See Also