codestory

Die Anleitung zu Spring Boot und Spring Data JPA

  1. Das Projekt Spring Boot erstellen
  2. Spring Boot & JPA konfigurieren
  3. Spring Data JPA (Bắt đầu nhanh)
  4. Controller
  5. Die Applikation laufen

1. Das Projekt Spring Boot erstellen

Auf Eclipse erstellen Sie ein Projekt Spring Boot.
Wählen Sie die im Projekt verwendeten Technologies, einschließend JPA und eine Databank, an die Sie sich gewöhnen.
Fügen Sie das folgende Konfigurationsstück in die File pom.xml ein wenn Sie mit der Datenbank Oracle arbeiten möchten:
** 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>
Die volle Inhalt der File 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 konfigurieren

Damit Spring Boot in die Datenbank verbinden kann, sollen Sie in die File applications.properties konfigurieren. Sie können irgendeine Datenbank, an die Sie sich gewöhnnen. Unter sind die 4 Konfiguration, die 4 üblichen Datenbanken entsprechen (MySQL, Oracle, SQL Server, PostGres).
Im Praxis erstellen Sie eine leere Datenbank (leeres Schema) mit dem Name von "mydatabase".JPA erstellt die in der Applikation Entity entsprechenden Tabelle.
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 (Bắt đầu nhanh)

In JPA entspricht jede Klasse Entity einer Tabelle in der Datenbank. Es gibt viele Tabelle in der Datenbank deshalb gibt es viele Klasse Entity. Sie arbeiten oft mit Entity, und müssen die Klasse DAO (Data Access Object) schreiben um durch Entity die Daten zu manipulieren. Das ist wirklich eine langweilige Arbeit
OK, Ich werde Sie sagen warum es langweilig ist. Stellen Sie sich vor, Sie haben in der Datenbank 2 Tabelle EMPLOYEE & DEPARTMENT, und Sie haben 2 entsprechenden Klasse EntityEmployee & Department.
Um mit Employee zu manipulieren, schreiben Sie eine Klasse DAO , die die ähnlichen Methode wie folgend umfasst:
  • Employee findById(Long id)
  • List<Employee> findAll()
  • List<Employee> findByName(String likeName)
  • .....
Natürlich zur Manipulierung mit Department machen Sie auch das ähnliche Ding. Und wenn die Anzahl von Entity zu viel ist, kostet es Ihre Zeit mehr
Spring Data JPA ist eine Bibliothek vom Spring. Nach dem Grundsatz vom Spring Data JPA brauchen Sie eine ausgeweiterte Interface - die Interface Repository<T,ID> definieren und deklarieren den Name der Methode mit Daten von diesem Entity. Spring Data JPA erstellt selbst eine Klasse, die diese Interface für Sie implementiert
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();
    }

}
Die Interface EmployeeRepository verlängert die Interface CrudRepository<Employee, Long>,. Sie hat die Methode um mit der entity Employee zu manipulieren. Spring Data JPA wird automatisch eine Klasse erstellen, die bei dem Runtime von Applikation diese Interface implementiert
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 wird die Kode für Ihre abstrakte Methode schreiben. So sollen Sie Spring Data JPA sagen, was Sie durch den Name der Methode möchten.
Keyword
Method
JPA Query
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
.....
Außerdem können Sie die Interface mit der anpassenden Methode erstellen. In dieser Situation müssen Sie die Klasse schreiben um die solche Interface zu implementieren
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. Die Applikation laufen

Anleitungen Spring Boot

Show More