Quote of the Day

more Quotes

Categories

Buy me a coffee

Building backend API with Spring data, Hibernate, JPA.

Published November 23, 2017 in Hibernate , Java , Spring Framework - 1 Comment

In this post, I’ll go over the setup of a sample backend RESTful API which utilizes Spring and Hibernate to simplify database operations and transaction management over a relational database.

Source code is available on GitHub: https://github.com/taithienbo/bookapp

Setting up the data source

Datasource is how you tell Spring how to connect to your backend database.

The below configurations are for starting up a H2 embedded database which supports Oracle SQL flavor for integration tests. 

@Bean
public DataSource dataSource() {
    EmbeddedDatabaseBuilder embeddedDatabaseBuilder = new EmbeddedDatabaseBuilder(  );
    DataSource dataSource = embeddedDatabaseBuilder.setType( EmbeddedDatabaseType.H2 ).setName( "testdb;" +
            "mode=Oracle" )
            .build();
    return dataSource;
}

The hsqldb library has a nice utitlity – the DatabaseManageSwing to manage the test database via a GUI, which I find convenience and helpful for debugging.

@Bean
public Server startDbManager() throws SQLException {
    DatabaseManagerSwing.main(new String[]
            {
                    "--url", "jdbc:h2:mem:testdb"
            });
    return Server.createWebServer(  );
}

For production, you probably want to connect to a standalone database such as MySQL or Oracle. As this sample application is based on a real web application that gets deployed to a WebLogic server, a common pattern is configuring the datasource on the actual server and lookup the configurations via JNDI as shown below.

@Bean(destroyMethod = "")
public DataSource dataSource() {
    try {
        Context context = new InitialContext(  );
        DataSource dataSource = ( DataSource ) context.lookup( appDatabasePropsLoader.getJndiDatasourceName() );
        return dataSource;
    } catch ( NamingException e ) {
        // unable to resolve data source info
        // log the exception
        LOGGER.error( "Failed to resolve data source.", e);
        return null;
    }
}

Configure EntityManagerFactory

An EntityManager manages the life cycles of entities within a persistent context. For each record in the database with an identity, there exists one entity instance in the persistence context.

An EntityManagerFactory creates EntityManager objects. More than one options exist for configuring an EntityManagerFactory. The LocalContainerEntityManagerFactoryBean is more flexible over the other option, the LocalEntityManagerFactoryBean. Per Spring docs, the LocalEntityManagerFactoryBean has limited configuration power, whereas the LocalContainerEntityManager bean is more powerful in which you can override the location of the persistence.xml file, specify location of JDBC data sources …

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setGenerateDdl( false );

    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setJpaVendorAdapter( vendorAdapter );
    factory.setPackagesToScan( "com.tbo.bookapp.domain" );
    factory.setDataSource( dataSource() );

    Properties properties = new Properties(  );
    properties.put( Environment.CURRENT_SESSION_CONTEXT_CLASS, org.hibernate.context.internal
            .ThreadLocalSessionContext.class);
    return factory;
}

The above codes specify Hibernate as the JPA provider, tell the EntityManager where to look for entities to manage, and the corresponding data source. In addition, it applies Hibernate specific settings via the setJpaProperties() method on the factory.

Configure JdbcTemplate

The below codes configure NamedParameterJdbcTemplate for using in cases where we need to provide our own custom queries in addition to Spring provided implementations of the CRUD operations. The NamedParameterJdbcTemplate allows the use of named parameters which I find  makes the codes easier to read and maintain.

@Bean
public NamedParameterJdbcTemplate namedParameterJdbcTemplate() {
    return new NamedParameterJdbcTemplate( dataSource() );
}

Configure PlatformTransactionManager

Lastly, we configure Spring PlatformTransactionManger for managing transactions. Spring provides a nice documentation on transaction management including the differences between global vs local transaction managers and other options. I recommend going over this documentation to understand  how Spring manages transaction and to pick the best option depending on your use cases.

@Bean
public PlatformTransactionManager platformTransactionManager() {
    JpaTransactionManager txManager = new JpaTransactionManager(  );
    txManager.setEntityManagerFactory( entityManagerFactory().getObject());
    txManager.afterPropertiesSet();

    return txManager;
}

Related Posts
No related posts for this content

1 comment