spring-boot
Spring boot + Spring Data JPA
Ricerca…
introduzione
Spring Boot semplifica la creazione di applicazioni e servizi a produzione di molle con il minimo sforzo. Favorisce la convenzione sulla configurazione.
Spring Data JPA , parte della più ampia famiglia Spring Data , semplifica l'implementazione di repository basati su JPA. Semplifica la creazione di app che utilizzano tecnologie di accesso ai dati.
Osservazioni
annotazioni
@Repository
: indica che una classe annotata è un "repository", un meccanismo per incapsulare il comportamento di archiviazione, recupero e ricerca che emula una raccolta di oggetti. I team che implementano modelli J2EE tradizionali come "Data Access Object" possono anche applicare questo stereotipo alle classi DAO, sebbene sia necessario prestare attenzione a comprendere la distinzione tra Data Access Object e gli archivi in stile DDD prima di farlo. Questa annotazione è uno stereotipo generico e le singole squadre potrebbero restringere la loro semantica e utilizzarla come appropriato.
@RestController
: Un'annotazione convenienza che è di per sé annotato con @Controller
e @ResponseBody.Types
che portano questa annotazione sono trattati come controller in cui @RequestMapping
metodi presuppongono @ResponseBody
semantica per impostazione predefinita.
@Service
: indica che una classe annotata è un "Servizio" (ad esempio una facciata di un servizio aziendale). Questa annotazione funge da specializzazione di @Component
, consentendo la @Component
automatica delle classi di implementazione tramite la scansione del percorso di classe.
@SpringBootApplication
: molti sviluppatori Spring Boot hanno sempre annotato la loro classe principale con @Configuration
, @EnableAutoConfiguration
e @ComponentScan
. Poiché queste annotazioni vengono utilizzate così frequentemente insieme (specialmente se si seguono le best practice sopra riportate), Spring Boot fornisce un'alternativa conveniente @SpringBootApplication
.
@Entity
: specifica che la classe è un'entità. Questa annotazione è applicata alla classe di entità.
Documentazione ufficiale
Il software pivotal ha fornito una documentazione piuttosto ampia su Spring Framework, e può essere trovata su
Esempio di base per l'integrazione JPA Spring Boot e Spring Data
Creeremo un'applicazione che memorizza i POJO in un database. L'applicazione utilizza Spring Data JPA per archiviare e recuperare i dati in un database relazionale. La sua caratteristica più interessante è la possibilità di creare implementazioni di repository automaticamente, in fase di runtime, da un'interfaccia di repository.
Classe principale
package org.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
Il metodo main()
usa il metodo SpringApplication.run()
Spring Boot per avviare un'applicazione. Si prega di notare che non esiste una singola riga di XML. Nessun file web.xml. Questa applicazione Web è al 100% pura Java e non devi occuparti della configurazione di qualsiasi impianto idraulico o infrastruttura.
Classe di entità
package org.springboot.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Greeting {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String text;
public Greeting() {
super();
}
public Greeting(String text) {
super();
this.text = text;
}
/* In this example, the typical getters and setters have been left out for brevity. */
}
Qui hai una classe di Greeting
con due attributi, l' id
e il text
. Hai anche due costruttori. Il costruttore predefinito esiste solo per il gusto di JPA. Non lo userai direttamente, quindi può essere designato come protected
. L'altro costruttore è quello che userai per creare istanze di Greeting
da salvare nel database.
La classe Greeting
è annotata con @Entity
, a indicare che si tratta di un'entità JPA. Per mancanza di un'annotazione @Table
, si presume che questa entità verrà mappata su una tabella denominata 'Saluto'.
La proprietà id
di Greeting è annotata con @Id
modo che JPA lo riconosca come ID dell'oggetto. La proprietà id
è anche annotata con @GeneratedValue
per indicare che l'ID deve essere generato automaticamente.
L'altra proprietà, il text
è stato annotato. Si presume che verrà mappato a una colonna che condivide lo stesso nome della proprietà stessa.
Proprietà transitorie
In una classe di entità simile a quella precedente, possiamo avere proprietà che non vogliamo essere persistenti nel database o create come colonne nel nostro database, forse perché vogliamo semplicemente impostarle in fase di runtime e usarle nella nostra applicazione, quindi possiamo avere quella proprietà annotata con l'annotazione @Transient.
package org.springboot.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Transient;
@Entity
public class Greeting {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String text;
@Transient
private String textInSomeLanguage;
public Greeting() {
super();
}
public Greeting(String text) {
super();
this.text = text;
this.textInSomeLanguage = getTextTranslationInSpecifiedLanguage(text);
}
/* In this example, the typical getters and setters have been left out for brevity. */
}
Qui si ha la stessa classe di saluto che ora ha una proprietà transitoria textInSomeLanguage
che può essere inizializzata e utilizzata in fase di runtime e non verrà mantenuta nel database.
Classe DAO
package org.springboot.repository;
import org.springboot.model.Greeting;
import org.springframework.data.repository.CrudRepository;
public interface GreetingRepository extends CrudRepository<Greeting, Long> {
List<Greeting> findByText(String text);
}
GreetingRepository
estende l'interfaccia CrudRepository
. Il tipo di entità e ID con cui lavora, Greeting
e Long
, sono specificati nei parametri generici su CrudRepository
. Estendendo CrudRepository
, GreetingRepository
eredita diversi metodi per lavorare con la persistenza dei Greeting
, compresi i metodi per salvare, eliminare e trovare le entità di Greeting
.
Vedi questa discussione per il confronto di CrudRepository
, PagingAndSortingRepository
, JpaRepository
.
Spring Data JPA consente inoltre di definire altri metodi di query semplicemente dichiarando la propria firma del metodo. Nel caso di GreetingRepository
, questo viene mostrato con un metodo findByText()
.
In una tipica applicazione Java, ci si aspetterebbe di scrivere una classe che implementa GreetingRepository
. Ma questo è ciò che rende Spring Data JPA così potente: non è necessario scrivere un'implementazione dell'interfaccia del repository. Spring Data JPA crea un'implementazione al volo quando si esegue l'applicazione.
Classe di servizio
package org.springboot.service;
import java.util.Collection
import org.springboot.model.Greeting;
public interface GreetingService {
Collection<Greeting> findAll();
Greeting findOne(Long id);
Greeting create(Greeting greeting);
Greeting update(Greeting greeting);
void delete(Long id);
}
Fagiolo di servizio
package org.springboot.service;
import java.util.Collection;
import org.springboot.model.Greeting;
import org.springboot.repository.GreetingRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class GreetingServiceBean implements GreetingService {
@Autowired
private GreetingRepository greetingRepository;
@Override
public Collection<Greeting> findAll() {
Collection<Greeting> greetings = greetingRepository.findAll();
return greetings;
}
@Override
public Greeting findOne(Long id) {
Greeting greeting = greetingRepository.findOne(id);
return greeting;
}
@Override
public Greeting create(Greeting greeting) {
if (greeting.getId() != null) {
//cannot create Greeting with specified Id value
return null;
}
Greeting savedGreeting = greetingRepository.save(greeting);
return savedGreeting;
}
@Override
public Greeting update(Greeting greeting) {
Greeting greetingPersisted = findOne(greeting.getId());
if (greetingPersisted == null) {
//cannot find Greeting with specified Id value
return null;
}
Greeting updatedGreeting = greetingRepository.save(greeting);
return updatedGreeting;
}
@Override
public void delete(Long id) {
greetingRepository.delete(id);
}
}
Controller Class
package org.springboot.web.api;
import java.util.Collection;
import org.springboot.model.Greeting;
import org.springboot.service.GreetingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/api")
public class GreetingController {
@Autowired
private GreetingService greetingService;
// GET [method = RequestMethod.GET] is a default method for any request.
// So we do not need to mention explicitly
@RequestMapping(value = "/greetings", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Collection<Greeting>> getGreetings() {
Collection<Greeting> greetings = greetingService.findAll();
return new ResponseEntity<Collection<Greeting>>(greetings, HttpStatus.OK);
}
@RequestMapping(value = "/greetings/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Greeting> getGreeting(@PathVariable("id") Long id) {
Greeting greeting = greetingService.findOne(id);
if(greeting == null) {
return new ResponseEntity<Greeting>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<Greeting>(greeting, HttpStatus.OK);
}
@RequestMapping(value = "/greetings", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Greeting> createGreeting(@RequestBody Greeting greeting) {
Greeting savedGreeting = greetingService.create(greeting);
return new ResponseEntity<Greeting>(savedGreeting, HttpStatus.CREATED);
}
@RequestMapping(value = "/greetings/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Greeting> updateGreeting(@PathVariable("id") Long id, @RequestBody Greeting greeting) {
Greeting updatedGreeting = null;
if (greeting != null && id == greeting.getId()) {
updatedGreeting = greetingService.update(greeting);
}
if(updatedGreeting == null) {
return new ResponseEntity<Greeting>(HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<Greeting>(updatedGreeting, HttpStatus.OK);
}
@RequestMapping(value = "/greetings/{id}", method = RequestMethod.DELETE)
public ResponseEntity<Greeting> deleteGreeting(@PathVariable("id") Long id) {
greetingService.delete(id);
return new ResponseEntity<Greeting>(HttpStatus.NO_CONTENT);
}
}
File delle proprietà dell'applicazione per il database MySQL
#mysql config
spring.datasource.url=jdbc:mysql://localhost:3306/springboot
spring.datasource.username=root
spring.datasource.password=Welcome@123
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto = update
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultNamingStrategy
#initialization
spring.datasource.schema=classpath:/data/schema.sql
File SQL
drop table if exists greeting;
create table greeting (
id bigint not null auto_increment,
text varchar(100) not null,
primary key(id)
);
pom.xml file
<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>org</groupId>
<artifactId>springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Costruire un JAR eseguibile
È possibile eseguire l'applicazione dalla riga di comando con Maven. Oppure puoi creare un singolo file JAR eseguibile che contenga tutte le dipendenze, le classi e le risorse necessarie ed eseguirlo. Ciò semplifica la spedizione, la versione e l'implementazione del servizio come un'applicazione per tutto il ciclo di vita dello sviluppo, in diversi ambienti e così via.
Esegui l'applicazione usando ./mvnw spring-boot:run
. Oppure puoi costruire il file JAR con il ./mvnw clean package
. Quindi è possibile eseguire il file JAR:
java -jar target/springboot-0.0.1-SNAPSHOT.jar