Spring Data JPA היא חלק ממשפחת Spring Data. Spring Data מקלה על יצירת יישומים שמשתמשים בדרכים חדשות לגשת לנתונים, כמו מסדי נתונים לא רלציוניים, מסגרות מפה-הפחתה, שירותי ענן, ותמיכה מתקדמת במסדי נתונים רלציוניים. מאמר זה ידון ב-Spring Data JPA. נסתכל גם על דוגמת יישום Spring Data JPA.
Spring Data JPA
חלק מהתכונות המעניינות שמספק על ידי Spring Data JPA הם:
- יצירה ותמיכה במאגרי נתונים שנוצרו עם Spring ו-JPA
- תמיכה בשאילתות QueryDSL ו-JPA
- ביקורת על מחלקות דומיין
- תמיכה בטעינה רכיבה, מיון, שאילתות דינמיות
- תמיכה במיפוי XML עבור יישויות
- הפחתת גודל הקוד עבור פעולות CRUD גנריות על ידי שימוש ב-CrudRepository
מתי להשתמש ב-Spring Data JPA?
I would say that if you need to quickly create a JPA-based repository layer that is mainly for CRUD operations, and you do not want to create abstract DAO, implementing interfaces, Spring Data JPA is a good choice.
דוגמת יישום Spring Data JPA
עבור דוגמא של Spring Data JPA שלנו, ניצור שירות אינטרנטי RESTful שיתחבר למסד נתונים של Postgresql. נממש פעולות בסיסיות של CRUD ונעבוד על נתוני דוגמא שכבר יצרנו.
נתוני דוגמא לדוגמא של Spring JPA
השתמש בשאילתה הבאה כדי ליצור טבלה במסד נתונים של Postgresql ולהוסיף נתוני מבחן.
create table people (
id serial not null primary key,
first_name varchar(20) not null,
last_name varchar(20) not null,
age integer not null
);
insert into people (id, first_name, last_name, age) values
(1, 'Vlad', 'Boyarskiy', 21),
(2,'Oksi', ' Bahatskaya', 30),
(3,'Vadim', ' Vadimich', 32);
מבנה פרויקט Spring Data JPA ב-Maven
התמונה למטה מראה את מבנה פרויקט Spring JPA הסופי. נתעקב אחרי כל אחד מהרכיבים בפרט לאחר מכן.
תלותי Maven של Spring Data JPA
נצטרך להוסיף את התלות הבאות לפרויקט דוגמא של Spring Data JPA שלנו.
postgresql
: מנהיג Java של Postgresql.spring-core
,spring-context
: מסתבר הקרן של Spring Framework.spring-webmvc
,jackson-databind
: ליישום REST של Spring.spring-data-jpa
,hibernate-entitymanager
: לתמיכה ב- Spring Data JPA וב- Hibernate.
למטה יש תוכן של קובץ הבנייה pom.xml הסופי.
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.journaldev</groupId>
<artifactId>springData</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>Spring Data JPA Maven Webapp</name>
<url>https://maven.apache.org</url>
<properties>
<spring.framework>4.3.0.RELEASE</spring.framework>
<postgres.version>42.1.4</postgres.version>
<serializer.version>2.8.1</serializer.version>
<spring.data>1.3.4.RELEASE</spring.data>
<hibernate.manager>4.2.5.Final</hibernate.manager>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.framework}</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgres.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.framework}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.framework}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>${spring.data}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.manager}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${serializer.version}</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
</build>
</project>
מחלקות הגדרת Spring
package com.journaldev.spring.config;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.ejb.HibernatePersistence;
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.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.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories("com.journaldev.spring.repository")
@PropertySource("classpath:database.properties")
public class DataConfig {
private final String PROPERTY_DRIVER = "driver";
private final String PROPERTY_URL = "url";
private final String PROPERTY_USERNAME = "user";
private final String PROPERTY_PASSWORD = "password";
private final String PROPERTY_SHOW_SQL = "hibernate.show_sql";
private final String PROPERTY_DIALECT = "hibernate.dialect";
@Autowired
Environment environment;
@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lfb = new LocalContainerEntityManagerFactoryBean();
lfb.setDataSource(dataSource());
lfb.setPersistenceProviderClass(HibernatePersistence.class);
lfb.setPackagesToScan("com.journaldev.spring.model");
lfb.setJpaProperties(hibernateProps());
return lfb;
}
@Bean
DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setUrl(environment.getProperty(PROPERTY_URL));
ds.setUsername(environment.getProperty(PROPERTY_USERNAME));
ds.setPassword(environment.getProperty(PROPERTY_PASSWORD));
ds.setDriverClassName(environment.getProperty(PROPERTY_DRIVER));
return ds;
}
Properties hibernateProps() {
Properties properties = new Properties();
properties.setProperty(PROPERTY_DIALECT, environment.getProperty(PROPERTY_DIALECT));
properties.setProperty(PROPERTY_SHOW_SQL, environment.getProperty(PROPERTY_SHOW_SQL));
return properties;
}
@Bean
JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
}
-
@Configuration
: זו הערה ב- spring שאומרת שזו מחלקת הגדרה. -
@EnableTransactionManagement
: ההערה הזו מאפשרת למשתמשים להשתמש בניהול עסקאות ביישום. -
@EnableJpaRepositories("com.journaldev.spring.repository")
: מציינת את מיקום מחלקות המאגרים. -
@PropertySource("classpath:database.properties")
: אומר שיש לנו קובץ מאפיינים ב-classpath שלנו. הערכים מתוך קובץ זה יוזרקו לתוך משתני סביבת ההרצה. תוכן קובץ database.properties מוצג למטה.driver=org.postgresql.Driver url=jdbc:postgresql://127.0.0.1:5432/postgres user=postgres password=postgres hibernate.dialect=org.hibernate.dialect.PostgreSQL82Dialect hibernate.show_sql=true
-
כדי להשתמש ב-Spring Data, עלינו תחילה להגדיר את ה-
DataSource
bean. לאחר מכן, עלינו להגדיר את ה-LocalContainerEntityManagerFactoryBean
bean. אנו זקוקים לבין זה כדי לשלוט על הישויות. בתוך ה-beans אלו, עליך לציין את ספק ההתמצאות שלך, כלומרHibernatePersistence
במקרה שלנו. -
השלב הבא הוא להגדיר פול עבור ניהול עסקאות. בדוגמתנו זה
JpaTransactionManager
. שימו לב שבלעדי הגדרת מנהל עסקאות לא נוכל להשתמש ב@Transactional
אנוטציה.
AppInitializer
ו WebConfig
הם להגדרת היישום שלנו כיישום רשת בלי להשתמש בקובץ web.xml.
מודל המחלקה
package com.journaldev.spring.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "people")
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "age")
private Integer age;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
public Person() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
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 "Person{" + "id=" + id + ", age=" + age + ", firstName='" + firstName + '\'' + ", lastName='" + lastName
+ '\'' + '}';
}
}
כאן יש לנו מספר אנוטציות חדשות. בואו נדבר עליהן בפרטיות יותר.
- @Entity: אנוטציה זו מאפשרת למנהל הישות להשתמש במחלקה זו ומכניסה אותה להקשר.
- @Table(שם = "אנשים"): משייכת מחלקה זו לטבלה במסד הנתונים.
@Id
: אומר ששדה זה הוא המפתח הראשי.@GeneratedValue(strategy = GenerationType.IDENTITY)
: מגדיר את האסטרטגיה ליצירת מפתח ראשי.@Column(name = "age")
: מציין עמודה במסד נתונים שבה תתייחס השדה הזה.
Spring Data JPA Repository
השלב הבא הוא ליצור את מאגר הנתונים של JPA.
package com.journaldev.spring.repository;
import org.springframework.data.repository.CrudRepository;
import com.journaldev.spring.model.Person;
import java.util.List;
public interface PersonRepository<P> extends CrudRepository<Person, Long> {
List<Person> findByFirstName(String firstName);
}
פועלים מ-CrudRepository
, נוכל לקרוא למספר רב של שיטות בלי לצורך לממש אותן בעצמנו. כמה מהשיטות הללו הם:
- save
- findOne
- exists
- findAll
- count
- delete
- deleteAll
ניתן גם להגדיר שיטות משלנו. שמות השיטות צריכים להשתמש במילות מפתח מיוחדות כמו "find", "order" עם שם המשתנים. מפתחי ה-Spring Data JPA ניסו לקחת בחשבון את רוב האפשרויות האפשריות שתצטרך. בדוגמא שלנו, השיטה findByFirstName(String firstName)
מחזירה את כל הרשומות מהטבלה בה השדה first_name
שווה ל-firstName
. זהו אחד מהתכונים החשובים ביותר של Spring Data JPA מכיוון שהוא יפחית הרבה מאוד קוד חוזר. גם יש פחות סיכונים לשגיאות מכיוון ששיטות אלו של Spring עברו בדיקה טובה על ידי פרויקטים רבים שכבר משתמשים בהם.
שירות מחלקת Spring
עכשיו שקוד Spring Data JPA שלנו מוכן, השלב הבא הוא ליצור מחלקת שירות ולהגדיר את השיטות שנצטרך לעבוד עם טבלת מסד הנתונים.
package com.journaldev.spring.services;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.journaldev.spring.model.Person;
import com.journaldev.spring.repository.PersonRepository;
@Service
public class PersonService {
@Autowired
PersonRepository<Person> personRepository;
@Transactional
public List<Person> getAllPersons() {
return (List<Person>) personRepository.findAll();
}
@Transactional
public List<Person> findByName(String name) {
return personRepository.findByFirstName(name);
}
@Transactional
public Person getById(Long id) {
return personRepository.findOne(id);
}
@Transactional
public void deletePerson(Long personId) {
personRepository.delete(personId);
}
@Transactional
public boolean addPerson(Person person) {
return personRepository.save(person) != null;
}
@Transactional
public boolean updatePerson(Person person) {
return personRepository.save(person) != null;
}
}
ההערה @Transactional
מציינת שהשיטה תופעל במסגרת העסקה. Spring ידאג לניהול העסקה.
מחלקת בקרת Spring
השלב הסופי הוא ליצור את מחלקת הבקרה כדי לחשוף את ה- API שלנו לעולם החיצוני.
package com.journaldev.spring.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
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.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.journaldev.spring.model.Person;
import com.journaldev.spring.services.PersonService;
@RestController
public class PersonController {
@Autowired
PersonService personService;
@RequestMapping(value = "/person/{id}", method = RequestMethod.GET)
public @ResponseBody Person getAllUsers(@PathVariable Long id) {
return personService.getById(id);
}
@RequestMapping(value = "/personByName/{name}", method = RequestMethod.GET)
public List<Person> getPersoneByName(@PathVariable String name) {
return personService.findByName(name);
}
@RequestMapping(value = "/person", method = RequestMethod.GET)
public List<Person> getAll() {
return personService.getAllPersons();
}
@RequestMapping(value = "/person/{id}", method = RequestMethod.DELETE)
public HttpStatus deletePersnone(@PathVariable Long id) {
personService.deletePerson(id);
return HttpStatus.NO_CONTENT;
}
@RequestMapping(value = "/person", method = RequestMethod.POST)
public HttpStatus insertPersone(@RequestBody Person person) {
return personService.addPerson(person) ? HttpStatus.CREATED : HttpStatus.BAD_REQUEST;
}
@RequestMapping(value = "/person", method = RequestMethod.PUT)
public HttpStatus updatePerson(@RequestBody Person person) {
return personService.updatePerson(person) ? HttpStatus.ACCEPTED : HttpStatus.BAD_REQUEST;
}
}
בדיקת Spring Data JPA
רק לבנות ולהתקין את הפרויקט בתוך מתקן ה- servlet האהוב עליך כמו Tomcat. התמונות למטה מציגות את התגובה לכמה משיחות ה- API.
Spring Data JPA קריאה לכל
Spring Data JPA קבלה לפי שם
Spring Data JPA יצירה
Spring Data JPA עדכון
Spring Data JPA מחיקה
זהו כל המדריך לדוגמא של Spring Data JPA. ניתן להוריד את הפרויקט הסופי מהקישור למטה.
הורדת פרויקט דוגמא ל-Spring Data JPA
התייחסות: אתר רשמי
Source:
https://www.digitalocean.com/community/tutorials/spring-data-jpa