Thursday, 7 March 2013

Spring JpaRepository Example (In-Memory)

This post describes a simple Spring JpaRepository example using an in memory HSQL database. The code example is available from GitHub in the Spring-JpaRepository directory. It is based on the Spring-MVC-With-Annotations example and information available here.

JPA Repository

We implement a dummy bean for this example:
@Entity
@AutoProperty
public class SomeItem {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long Id;

    private String someText;

    /* ...Setters & Getters */

}
and the corresponding JpaRepository:
@Transactional
public interface SomeItemRepository
        extends JpaRepository<SomeItem, Long> {

}

Service & Controller

Next, we implement a service where our repository will be injected. We also populate the repository with dummy data:
@Service
@Repository
public class SomeItemService {

    @Autowired
    private SomeItemRepository someItemRepository;

    @PostConstruct
    @Transactional
    public void populate() {

        SomeItem si = new SomeItem();
        si.setSomeText("aaa");
        someItemRepository.saveAndFlush(si);

        si = new SomeItem();
        si.setSomeText("bbb");
        someItemRepository.saveAndFlush(si);

        si = new SomeItem();
        si.setSomeText("ccc");
        someItemRepository.saveAndFlush(si);

    }

    @Transactional(readOnly=true)
    public List<SomeItem> getAll() {

        return someItemRepository.findAll();

    }

    @SuppressWarnings("AssignmentToMethodParameter")
    @Transactional
    public SomeItem saveAndFlush(SomeItem si) {

        if ( si != null ) {
            si = someItemRepository.saveAndFlush(si);
        }

        return si;

    }

    @Transactional
    public void delete(long id) {

        someItemRepository.delete(id);

    }

}
and a controller:
@Controller
public class MyController {

    @Autowired
    private SomeItemService someItemService;

    @RequestMapping(value = "/")
    public ModelAndView index() {

        ModelAndView result = new ModelAndView("index");
        result.addObject("items", this.someItemService.getAll());

        return result;

    }

    @RequestMapping(value = "/delete/{id}")
    public String delete(
        @PathVariable(value="id") String id) {

        this.someItemService.delete(Long.parseLong(id));

        return "redirect:/";

    }

    @RequestMapping(value = "/create")
    @SuppressWarnings("AssignmentToMethodParameter")
    public String add() {

        SomeItem si = new SomeItem();
        si.setSomeText("Time is: " + System.currentTimeMillis());

        this.someItemService.saveAndFlush(si);

        return "redirect:/";

    }

}

JPA Configuration

On top of creating an entity manager based on an in-memeory instance of HSQL database, we enable JPA repositories with the @EnableJpaRepositories annotation:
@Configuration
@EnableJpaRepositories(basePackages={"com.jverstry"})
@EnableTransactionManagement
public class JpaConfig implements DisposableBean {

    private EmbeddedDatabase ed;

    @Bean(name="hsqlInMemory")
    public EmbeddedDatabase hsqlInMemory() {

        if ( this.ed == null ) {
            EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
            this.ed = builder.setType(EmbeddedDatabaseType.HSQL).build();
        }

        return this.ed;

    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(){

        LocalContainerEntityManagerFactoryBean lcemfb
            = new LocalContainerEntityManagerFactoryBean();

        lcemfb.setDataSource(this.hsqlInMemory());
        lcemfb.setPackagesToScan(new String[] {"com.jverstry"});

        lcemfb.setPersistenceUnitName("MyPU");

        HibernateJpaVendorAdapter va = new HibernateJpaVendorAdapter();
        lcemfb.setJpaVendorAdapter(va);

        Properties ps = new Properties();
        ps.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
        ps.put("hibernate.hbm2ddl.auto", "create");
        lcemfb.setJpaProperties(ps);

        lcemfb.afterPropertiesSet();

        return lcemfb;

    }

    @Bean
    public PlatformTransactionManager transactionManager(){

        JpaTransactionManager tm = new JpaTransactionManager();

        tm.setEntityManagerFactory(
            this.entityManagerFactory().getObject() );

        return tm;

    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
        return new PersistenceExceptionTranslationPostProcessor();
    }

    @Override
    public void destroy() {

        if ( this.ed != null ) {
            this.ed.shutdown();
        }

    }

}

The JSP Page

We create a simple page to list existing items with a delete link, and the possibility to create new items:

 Running The Example

One can run it using the maven tomcat:run goal. Then, browse:

  http://localhost:9191/spring-jparepository/

More Spring related posts here.