In this tutorial I’ll show you how to use Spring Data JPA to integrate a relational database (PostgreSQL in my example) into a Spring Boot application.
I’ll use these technologies and tools:
In case you’re using another IDE like Eclipse, Netbeans or IntelliJ IDEA, you can create a new Maven project and add to the pom.xml file the dependencies listed in the next paragraph.
I’m using PostgreSQL, but this example works fine also with other relational databases. For example, if you want to use MySQL, all you need to do is replace the postgresql dependency with the mysql one.
If you’re using MySQL, pay attention to replace line 36 of JpaConfig.java with this one: vendorAdapter.setDatabase(Database.MYSQL); and change the relative values in the jpa.properties file:
Then I code the mapping object model. The @Table(name = "persons") annotation specifies in which table to save a Person object. The @GeneratedValue(strategy = GenerationType.IDENTITY) is quite general. In PostgreSQL I have defined the id attribute as SERIAL. In MySQL you probably want to use AUTO_INCREMENT. That’s just fine, it works with both of them.
I’ll use these technologies and tools:
- Spring Tool Suite (STS) 3.8.4.RELEASE
- Java 8
- Spring Boot 1.5.3.RELEASE
- Maven 3.3.9
- PostgreSQL 9.6.2
1. The Project Structure
The final folder structure of our project.2. Create a new Spring Boot project
If you’re using STS, you can easily create a starter project by either selecting File > New > Spring Starter Project from the main menu or right-clicking on the Package Explorer and select New > Spring Starter Project.In case you’re using another IDE like Eclipse, Netbeans or IntelliJ IDEA, you can create a new Maven project and add to the pom.xml file the dependencies listed in the next paragraph.
3. Maven Dependencies
spring-boot-starter-data-jpa is the fundamental dependency for our project, then we need the driver for whatever SQL database we have chosen, in this case postgresql.- pom.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>com.thomasvitale</groupId>
- <artifactId>Application</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>Application</name>
- <description>Demo application for Spring Data JPA</description>
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>1.5.3.RELEASE</version>
- <relativePath/> <!-- lookup parent from repository -->
- </parent>
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- <java.version>1.8</java.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-jpa</artifactId>
- </dependency>
- <dependency>
- <groupId>org.postgresql</groupId>
- <artifactId>postgresql</artifactId>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
- </project>
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <scope>runtime</scope>
- </dependency>
4. Spring Configuration using Java Annotations and Hibernate
Spring lets you use either Java configuration or XML configuration or a mix of the two. I’ll use a pure Java configuration. There are a few implementations of JPA, in this example Hibernate is used. Its properties are stored in a dedicated file.- JpaConfig.java
- package com.thomasvitale;
- import java.util.Properties;
- import javax.persistence.EntityManagerFactory;
- import javax.sql.DataSource;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.context.annotation.PropertySource;
- import org.springframework.core.env.Environment;
- import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
- import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
- import org.springframework.jdbc.datasource.DriverManagerDataSource;
- import org.springframework.orm.jpa.JpaTransactionManager;
- import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
- import org.springframework.orm.jpa.vendor.Database;
- import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
- import org.springframework.transaction.PlatformTransactionManager;
- import org.springframework.transaction.annotation.EnableTransactionManagement;
- @Configuration
- @EnableTransactionManagement
- @EnableJpaRepositories(basePackages = "com.thomasvitale.repository")
- @PropertySource("classpath:jpa.properties")
- public class JpaConfig {
- @Autowired
- private Environment env;
- @Bean
- public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
- HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
- vendorAdapter.setDatabase(Database.POSTGRESQL);
- vendorAdapter.setGenerateDdl(true);
- LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
- em.setDataSource(dataSource());
- em.setPackagesToScan("com.thomasvitale.model");
- em.setJpaVendorAdapter(vendorAdapter);
- em.setJpaProperties(additionalProperties());
- return em;
- }
- @Bean
- public DataSource dataSource(){
- DriverManagerDataSource dataSource = new DriverManagerDataSource();
- dataSource.setDriverClassName(env.getProperty("hibernate.connection.driver_class"));
- dataSource.setUrl(env.getProperty("hibernate.connection.url"));
- dataSource.setUsername(env.getProperty("hibernate.connection.username"));
- dataSource.setPassword(env.getProperty("hibernate.connection.password"));
- return dataSource;
- }
- @Bean
- public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
- JpaTransactionManager transactionManager = new JpaTransactionManager();
- transactionManager.setEntityManagerFactory(emf);
- return transactionManager;
- }
- @Bean
- public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
- return new PersistenceExceptionTranslationPostProcessor();
- }
- Properties additionalProperties() {
- Properties properties = new Properties();
- properties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
- properties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
- properties.setProperty("hibernate.current_session_context_class", env.getProperty("hibernate.current_session_context_class"));
- return properties;
- }
- }
- jpa.properties
- hibernate.connection.username=db-user
- hibernate.connection.password=db-password
- hibernate.connection.url=jdbc:postgresql://localhost:5432/app
- hibernate.connection.driver_class=org.postgresql.Driver
- hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
- hibernate.current_session_context_class=thread
- hibernate.hbm2ddl.auto=validate
- hibernate.show_sql=false
- hibernate.format_sql=false
- hibernate.connection.url=jdbc:mysql://localhost:3306/app
- hibernate.connection.driver_class=com.mysql.jdbc.Driver
- hibernate.dialect=org.hibernate.dialect.MySQLDialect
5. Person Model
For the Person entity, first of all I create a new table (persons) in my PostgreSQL database (called app).- CREATE TABLE persons(
- id SERIAL,
- firstName VARCHAR(32),
- lastName VARCHAR(32),
- PRIMARY KEY(id)
- );
- Person.java
- package com.thomasvitale.model;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- import javax.persistence.Table;
- @Entity
- @Table(name = "persons")
- public class Person {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Integer id;
- private String firstName;
- private String lastName;
- public Person() {
- }
- public Person(String firstName, String lastName) {
- this.firstName = firstName;
- this.lastName = lastName;
- }
- public Integer getId() {
- return id;
- }
- public void setId(Integer id) {
- this.id = id;
- }
- public String getFirstName() {
- return firstName;
- }
- public void setFirstName(String firstName) {
- this.firstName = firstName;
- }
- public String getLastName() {
- return lastName;
- }
- public void setLastName(String lastName) {
- this.lastName = lastName;
- }
- @Override
- public String toString() {
- return firstName + " " + lastName;
- }
- }
6. Person Repository
Our PersonRepository extends the JpaRepository interface, that provides us with a lot of operations out-of-the-box, including the standard CRUD operations. You can also add custom operations like findByFirstName and findByLastName without writing any implementation: Spring Data JPA creates them for you!- PersonRepository.java
- package com.thomasvitale.repository;
- import java.util.List;
- import org.springframework.data.jpa.repository.JpaRepository;
- import org.springframework.stereotype.Repository;
- import com.thomasvitale.model.Person;
- @Repository
- public interface PersonRepository extends JpaRepository<Person, Integer> {
- public Person findByFirstName(String firstName);
- public List<Person> findByLastName(String lastName);
- }
7. Demo
Let’s try some CRUD operations to test our application.- package com.thomasvitale;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.CommandLineRunner;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import com.thomasvitale.model.Person;
- import com.thomasvitale.repository.PersonRepository;
- @SpringBootApplication
- public class Application implements CommandLineRunner {
- @Autowired
- PersonRepository personRepository;
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
- @Override
- public void run(String... arg0) throws Exception {
- // Save three Person documents on PostgreSQL
- personRepository.save(new Person("Sheldon", "Cooper"));
- personRepository.save(new Person("Missy", "Cooper"));
- personRepository.save(new Person("Leonard", "Hofstadter"));
- // Get all the people
- System.out.println(">>> All the people in the database:");
- personRepository.findAll().forEach(System.out::println);
- // Get all the people with a specific last name
- System.out.println(">>> All people with last name = 'Cooper'");
- personRepository.findByLastName("Cooper").forEach(System.out::println);
- // Update an individual person
- Person person = personRepository.findByFirstName("Sheldon");
- person.setFirstName("Shelly");
- personRepository.save(person);
- // Delete all
- personRepository.deleteAll();
- }
- }
0 comentarios:
Publicar un comentario