Руководство Spring Boot и Spring Data JPA

View more Tutorials:

1- Создать проект Spring Boot

На  Eclipse создать проект Spring Boot.
Выбрать технологии для использования в данном проекте, включая  JPA и определенную базу данных которая вам знакома.
Добавить следующий сниппет конфигурации в файл  pom.xml если вы хотите работать с базой данных  Oracle:
** Oracle **
<dependencies>
   <dependency>
      <groupId>com.oracle</groupId>
      <artifactId>ojdbc7</artifactId>
      <version>12.1.0.2</version>
   </dependency>
</dependencies>

<repositories>
   <!-- Repository for ORACLE ojdbc6. -->
   <repository>
      <id>codelds</id>
      <url>https://code.lds.org/nexus/content/groups/main-repo</url>
   </repository>
</repositories>
Полное содержание файла  pom.xml:
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.example</groupId>
    <artifactId>SpringBootDataJPA</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>SpringBootDataJPA</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.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.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>mssql-jdbc</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc7</artifactId>
            <version>12.1.0.2</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <repositories>
        <!-- Repository for ORACLE ojdbc6. -->
        <repository>
            <id>codelds</id>
            <url>https://code.lds.org/nexus/content/groups/main-repo</url>
        </repository>
    </repositories>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
SpringBootDataJpaApplication.java
package org.o7planning.sbdatajpa;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootDataJpaApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootDataJpaApplication.class, args);
    }
    
}

2- Конфигурация Spring Boot & JPA

Чтобы  Spring Boot мог подключиться к базе данных, вам нужно конфигурировать в файле  applications.properties. Вы можете использовать любую базу данных которая вам знакома, ниже являются 4 соответствующих конфигураций для 4 самых распространенных видов базы данных ( MySQL, Oracle, SQL Server, PostGres).
На практике, создадим пустую базу данных (пустая schema) с названием  "mydatabase", JPA создаст соответствующую таблицу к Entity включенная в приложении.
application.properties (MySQL)
# ===============================
# DATABASE
# ===============================

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase
spring.datasource.username=root
spring.datasource.password=12345

# ===============================
# JPA / HIBERNATE
# ===============================

spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
application.properties (Oracle)
# ===============================
# DATABASE
# ===============================

spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver

spring.datasource.url=jdbc:oracle:thin:@localhost:1521:db12c
spring.datasource.username=mydatabase
spring.datasource.password=12345


# ===============================
# JPA / HIBERNATE
# ===============================

spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
application.properties (SQL Server)
# ===============================
# DATABASE
# ===============================

spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.url=jdbc:sqlserver://localhost\\SQLEXPRESS:1433;databaseName=mydatabase
spring.datasource.username=sa
spring.datasource.password=12345


# ===============================
# JPA / HIBERNATE
# ===============================

spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
application.properties (PostGres)
# ===============================
# DATABASE CONNECTION
# ===============================

spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/mydatabase
spring.datasource.username=postgres
spring.datasource.password=12345

# ===============================
# JPA / HIBERNATE
# ===============================

spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect


# Fix Postgres JPA Error:
# Method org.postgresql.jdbc.PgConnection.createClob() is not yet implemented.
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false

3- Spring Data JPA (Quick Start)

В  JPA каждый класс  Entity будет соответствовать таблице в базе данных. Имеется очень много таблиц в базе данных поэтому будет очень много классов  Entity. Вам часто приходится работать с Entity, и нужно написать классы  DAO ( Data Access Object) чтобы манипулировать с данными через эти  Entity, это на самом деле надоедливая работа.
OK, я скажу вам почему это надоедливая работа. Представьте у вас есть 2 таблицы в базе даннх это EMPLOYEE & DEPARTMENT, и у вас есть 2 соответствующих класса  Entity это  Employee & Department.
Для манипуляции с  Employee вы пишете класс  DAO включая аналогичные следующие методы:
  • Employee findById(Long id)
  • List<Employee> findAll()
  • List<Employee> findByName(String likeName)
  • .....
     
Конечно, чтобы манипулировать с  Department вам так же нужно сделать похожие действия, и если количество  Entity слишком большое, это займет много вашего времени.
Spring Data JPA это библиотека  Spring. По правилу  Spring Data JPA вам нужно только дать определение расширенного интерфейса  Repository<T,ID>, и объявить названия методов для манипуляции с данными этого Entity. Spring Data JPA сам создаст для вас класс применения (implements) того интерфейса. Конечно, названия методов должны следовать правилам выдвинутые Spring Data JPA.
Employee.java
package org.o7planning.sbdatajpa.entity;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
@Table(name = "EMPLOYEE")
public class Employee {

    @Id
    private Long id;

    @Column(name = "Emp_No", length = 30, nullable = false)
    private String empNo;

    @Column(name = "Full_Name", length = 128, nullable = false)
    private String fullName;

    @Temporal(TemporalType.DATE)
    @Column(name = "Hire_Date", nullable = false)
    private Date hireDate;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getEmpNo() {
        return empNo;
    }

    public void setEmpNo(String empNo) {
        this.empNo = empNo;
    }

    public String getFullName() {
        return fullName;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }

    public Date getHireDate() {
        return hireDate;
    }

    public void setHireDate(Date hireDate) {
        this.hireDate = hireDate;
    }

    @Override
    public String toString() {
        return this.getEmpNo() + ", " + this.getFullName();
    }

}
Интерфейс  EmployeeRepository расширяет (extends) интерфейс CrudRepository<Employee, Long>, он имеет методы для манипуляции с entity Employee. Spring Data JPA автоматически создает класс применения (implements) данного интерфейса во время запуска приложения.
EmployeeRepository.java
package org.o7planning.sbdatajpa.repository;

import java.util.Date;
import java.util.List;

import org.o7planning.sbdatajpa.entity.Employee;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;

// This is an Interface.
// No need Annotation here.
public interface EmployeeRepository extends CrudRepository<Employee, Long> { // Long: Type of Employee ID.

    Employee findByEmpNo(String empNo);

    List<Employee> findByFullNameLike(String fullName);

    List<Employee> findByHireDateGreaterThan(Date hireDate);

    @Query("SELECT coalesce(max(e.id), 0) FROM Employee e")
    Long getMaxId();

}
Spring Data JPA напишет код для ваших абстрактных методов, поэтому вам нужно сказать Spring Data JPA что вы хотите через названия методов.
Keyword Sample Equivalent to
GreaterThan findByAgeGreaterThan(int age) Select e from Person e where e.age > :age
LessThan findByAgeLessThan(int age) Select e from Person e where e.age < :age
Between findByAgeBetween(int from, int to) Select e from Person e where e.age between :from and :to
IsNotNull, NotNull findByFirstnameNotNull() Select e from Person e where e.firstname is not null
IsNull, Null findByFirstnameNull() Select e from Person e where e.firstname is null
Like findByFirstnameLike(String name) Select e from Person e where e.firstname like :name
(No keyword) findByFirstname(String name) Select e from Person e where e.firstname = :name
Not findByFirstnameNot(String name) Select e from Person e where e.firstname <> :name
 .....    
Помимо этого вы так же можете создать интерфейсы с кастомизированными методами. В данной ситуации вы должны сами написать класс применения (implements) того интерфейса.
EmployeeRepositoryCustom.java
package org.o7planning.sbdatajpa.repository;

import java.util.Date;

public interface EmployeeRepositoryCustom {
    
    public Long getMaxEmpId();

    public long updateEmployee(Long empId, String fullName, Date hireDate);

}
EmployeeRepositoryCustomImpl.java
package org.o7planning.sbdatajpa.repository;

import java.util.Date;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import org.o7planning.sbdatajpa.entity.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class EmployeeRepositoryCustomImpl implements EmployeeRepositoryCustom {

    @Autowired
    EntityManager entityManager;

    @Override
    public Long getMaxEmpId() {
        try {
            String sql = "SELECT coalesce(max(e.id), 0) FROM Employee e";
            Query query = entityManager.createQuery(sql);
            return (Long) query.getSingleResult();
        } catch (NoResultException e) {
            return 0L;
        }
    }

    @Override
    public long updateEmployee(Long empId, String fullName, Date hireDate) {
        Employee e = entityManager.find(Employee.class, empId);
        if (e == null) {
            return 0;
        }
        e.setFullName(fullName);
        e.setHireDate(hireDate);
        entityManager.flush();
        return 1;
    }

}

4- Controller

MainController.java
package org.o7planning.sbdatajpa.controller;

import java.util.Date;
import java.util.List;
import java.util.Random;

import org.o7planning.sbdatajpa.entity.Employee;
import org.o7planning.sbdatajpa.repository.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MainController {

    @Autowired
    private EmployeeRepository employeeRepository;

    private static final String[] NAMES = new String[] { "Tom", "Jerry", "Donald" };

    @ResponseBody
    @RequestMapping("/")
    public String home() {
        String html = "";
        html += "<ul>";
        html += " <li><a href='/testInsert'>Test Insert</a></li>";
        html += " <li><a href='/showAllEmployee'>Show All Employee</a></li>";
        html += " <li><a href='/showFullNameLikeTom'>Show All 'Tom'</a></li>";
        html += " <li><a href='/deleteAllEmployee'>Delete All Employee</a></li>";
        html += "</ul>";
        return html;
    }

    @ResponseBody
    @RequestMapping("/testInsert")
    public String testInsert() {

        Long empIdMax = this.employeeRepository.getMaxId();

        Employee employee = new Employee();

        int random = new Random().nextInt(3);

        long id = empIdMax + 1;
        String fullName = NAMES[random] + " " + id;

        employee.setId(id);
        employee.setEmpNo("E" + id);
        employee.setFullName(fullName);
        employee.setHireDate(new Date());
        this.employeeRepository.save(employee);

        return "Inserted: " + employee;
    }

    @ResponseBody
    @RequestMapping("/showAllEmployee")
    public String showAllEmployee() {

        Iterable<Employee> employees = this.employeeRepository.findAll();

        String html = "";
        for (Employee emp : employees) {
            html += emp + "<br>";
        }

        return html;
    }

    @ResponseBody
    @RequestMapping("/showFullNameLikeTom")
    public String showFullNameLikeTom() {

        List<Employee> employees = this.employeeRepository.findByFullNameLike("Tom");

        String html = "";
        for (Employee emp : employees) {
            html += emp + "<br>";
        }

        return html;
    }

    @ResponseBody
    @RequestMapping("/deleteAllEmployee")
    public String deleteAllEmployee() {

        this.employeeRepository.deleteAll();
        return "Deleted!";
    }

}
 

5- Запуск приложения

View more Tutorials: