toogle sidebar button

Configuration

Dependencies

Add Spring dependencies in pom.xml :

<properties>
    ...
    <hibernate.version>4.1.9.Final</hibernate.version>
</properties>

<dependencies>
    ...
    <!-- Spring -->
    ...
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <!-- JPA Vendor -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>${hibernate.version}</version>
    </dependency>
</dependencies>

Install and configure database

  • Database type: MySQL
  • Host: localhost
  • Port: 3306
  • Database: hello_spring
  • Login: root
  • Password: root

Configure MySQL Driver

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.22</version>
</dependency>

Configure Datasource in Spring

For development purposes:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/hello_spring"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</bean>

For more datasources possibilities check: Datasources

Configure local Transaction Manager

<!-- Transactions -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="transactionManager" />

Configure EntityManager

Option 1: without persistence.xml :

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="generateDdl" value="true" />
            <property name="showSql" value="true" />
        </bean>
    </property>
    <property name="packagesToScan" value="io.github.kospiotr.model"/>
    <property name="dataSource" ref="dataSource"/>
</bean>

Option 2: with persistence.xml :

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
    </property>
    <property name="dataSource" ref="dataSource"/>
</bean>

Then META-INF/persistence.xml:

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
             http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">
    <persistence-unit name="PU" transaction-type="RESOURCE_LOCAL">
        <properties>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
        </properties>
    </persistence-unit>
</persistence>

More configuration properties: https://docs.jboss.org/hibernate/core/4.3/manual/en-US/html_single#configuration-optional

Example Model

Java model

import javax.persistence.Entity;
import javax.persistence.Id;
 
@Entity
public class Product {
 
    @Id
    private Integer id;
    private String name;
 
    public Product() {
    }
 
    public Product(Integer id, String name) {
        this.id = id;
        this.name = name;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
 
    @Override
    public String toString() {
        return "Product [id=" + id + ", name=" + name + "]";
    }
 
}

Database schema

No need if hibernate.hbm2ddl.auto='create-drop'.

CREATE TABLE `Product` (
  `id` int(11) unsigned NOT NULL,
  `name` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Pure JPA

DAO

@Component
public class ProductRepository {

	@PersistenceContext
	private EntityManager em;

	public Product findById(Integer productId) {
		return em.find(Product.class, productId);
	}

	public List<Product> findAll() {
		return em.createQuery("SELECT p FROM Product p").getResultList();
	}

	public Product create(Product product) {
		em.persist(product);
		return product;
	}

	public Product update(Product product) {
		return em.merge(product);
	}

	public void delete(Integer id) {
		Product toRemove = findById(id);
		if (toRemove == null) {
			throw new RuntimeException("Can't find Product with given id: " + id);
		}
		em.remove(toRemove);
	}
}

Service

@Component
public class ProductService {

	@Autowired
	private ProductRepository productDao;

	@Transactional(readOnly = true)
	public List<Product> findAll() {
		return productDao.findAll();
	}

	public Product findById(Integer productId) {
		return productDao.findById(productId);
	}

	@Transactional
	public Product save(Product product) {
		if (product.getId() == null) {
			return productDao.create(product);
		} else {
			return productDao.update(product);
		}
	}

	@Transactional
	public void delete(Integer id) {
		productDao.delete(id);
	}
}

Spring Data

What is it for?

Simplify JPA access by removing boilerplate code and introduce higher level of abstraction. Thanks to Spring Data we can focus on business value.

Dependency

<dependencies>
	...
	<dependency>
	    <groupId>org.atteo.moonshine</groupId>
	    <artifactId>spring-data</artifactId>
	    <version>${spring-data.version}</version>
	</dependency>
</dependencies>

Configuration

    <jpa:repositories base-package="io.github.kospiotr.repository"/>

DAO

public interface ProductRepository extends JpaRepository<Product, Integer> {

}

Service

@Component
public class ProductService {

	@Autowired
	private ProductRepository productRepository;

	@Transactional(readOnly = true)
	public List<Product> findAll() {
		return productRepository.findAll();
	}

	public Product findById(Integer productId) {
		return productRepository.findOne(productId);
	}

	@Transactional
	public Product save(Product product) {
		return productRepository.save(product);
	}

	@Transactional
	public void delete(Integer id) {
		productRepository.delete(id);
	}
}

Custom by property

public interface ProductRepository extends JpaRepository<Product, Integer> {

  List<Product> findByName(String name); 
}

Custom JPQL

public interface ProductRepository extends JpaRepository<Product, Integer> {

  @Query("<JPQ statement here>")
  List<Product> findBySomeInputs(Integer age); 
}