Thursday, December 11, 2014

Using Spring Data JPA

Spring Data JPA is a library / framework that adds an extra layer of abstraction on the top of our JPA provider.
DAO Structure
Using JpaRepository and Entity Manager persistence

Configuration:
 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/data/jpa
        http://www.springframework.org/schema/data/jpa/spring-jpa.xsd

        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
        ">

    <!-- Enables the Spring MVC @Controller programming model -->
    <mvc:annotation-driven />
   
    <jpa:repositories base-package="com.journaldev.spring.repository"/>

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving
        up static resources in the ${webappRoot}/resources directory -->
    <mvc:resources mapping="/resources/**" location="/resources/" />

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources
        in the /WEB-INF/views directory -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url"
            value="jdbc:mysql://localhost:3306/spring-data-jpa" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>
   
    <bean id="jpaVendorAdapter"
        class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="showSql" value="true"/>
        <property name="generateDdl" value="true"/>
        <property name="database" value="MYSQL"/>
    </bean>

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
        <!-- spring based scanning for entity classes-->
        <property name="packagesToScan" value="com.journaldev.spring.model"/>
    </bean>

    <bean id="personDAO" class="com.journaldev.spring.dao.PersonDAOImpl">
        <property name="em" ref="entityManagerFactory" />
    </bean>
    <bean id="personService" class="com.journaldev.spring.service.PersonServiceImpl">
        <property name="personDAO" ref="personDAO"></property>
    </bean>
   
    <context:component-scan base-package="com.journaldev.spring" />
   
    <bean id="transactionManager"
        class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>



Usage:

import org.springframework.data.jpa.repository.JpaRepository;
import com.journaldev.spring.model.Person;
public interface PersonRepository extends JpaRepository<Person, Integer> {

}


Add to where to use:
@Autowired
private PersonRepository personRepository;

To add function to JpaRepository, we have 3 ways:
* Declare method name by combine keyword and fieldName
public List<Person> findByLastName(String lastName);

* Using NamedQuery

@Entity
@NamedQuery(name = "Person.findByName", query = "SELECT p FROM Person p WHERE LOWER(p.lastName) = LOWER(?1)")
@Table(name = "persons")
public class Person {
     
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
Then add method which name match namedQuery name:
public List<Person> findByName(String lastName);
* Using @Query at method definition

@Query("SELECT p FROM Person p WHERE LOWER(p.lastName) = LOWER(:lastName)")
    public List<Person> find(@Param("lastName") String lastName);

Entity Manager

 @PersistenceContext
    private EntityManager em;

 
 @Override
    public List<Person> findByCountry(String country) {
        List<Person> results = em.createNamedQuery("findByCountry").setParameter(1, country).getResultList();
        return results;
    }


EntityManager allow to run native Sql by em.createNativeQuery(String sqlString).

References:
http://www.petrikainulainen.net/spring-data-jpa-tutorial/ 

2 comments: