Spring Data JPA هو جزء من عائلة Spring Data. يجعل Spring Data من السهل إنشاء تطبيقات تعمل بناءً على Spring والتي تستخدم طرقًا جديدة للوصول إلى البيانات ، مثل قواعد البيانات غير العلاقية ، وإطارات تقليل الخريطة ، وخدمات السحابة ، بالإضافة إلى دعم قوي لقواعد البيانات العلاقية المتقدمة. ستتناول هذه المقالة حول 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. سنقوم بتنفيذ العمليات الأساسية للقراءة والإضافة والتحديث والحذف، وسنعمل على بيانات عينة لدينا بالفعل.
بيانات عينة لمثال 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
: برنامج تشغيل Postgresql لجافا.spring-core
،spring-context
: تعتمد على النواة الأساسية لـ إطار العمل سبرينج.spring-webmvc
،jackson-databind
: لتطبيقات سبرينج ريست.spring-data-jpa
،hibernate-entitymanager
: لدعم سبرينج داتا JPA و هيبرنيت.
فيما يلي محتوى ملف البناء 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>
فئات تكوين سبرينج
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
: تعني هذه التعليقة سبرينج أنها فئة تكوين. -
@EnableTransactionManagement
: تتيح هذه التعليقة للمستخدمين استخدام إدارة المعاملات في التطبيق. -
@EnableJpaRepositories("com.journaldev.spring.repository")
: تشير إلى مكان وجود فئات المستودعات. -
@PropertySource("classpath:database.properties")
: يشير إلى وجود ملف خاصية في مسار الفئات. سيتم حقن قيم هذا الملف في المتغيرات البيئية. يتم عرض محتويات ملف 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
. ثم نحتاج إلى تكوين حبةLocalContainerEntityManagerFactoryBean
. نحتاج هذه الحبة للتحكم في الكيانات. في هذه الحبات ، يجب عليك تحديد مزود الاستمرارية أيHibernatePersistence
في حالتنا. -
الخطوة التالية هي تكوين الـ bean لإدارة الـ transaction. في مثالنا، نحن نستخدم
JpaTransactionManager
. يجب ملاحظة أنه بدون تكوين مدير الـ transaction، لا يمكننا استخدام التعليق البرمجي@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(name = “people”): يقوم بربط الفئة مع جدول في قاعدة البيانات.
@Id
: يشير إلى أن هذا الحقل هو المفتاح الأساسي.@GeneratedValue(strategy = GenerationType.IDENTITY)
: يحدد استراتيجية توليد المفتاح الأساسي.@Column(name = "age")
: يشير إلى عمود في قاعدة البيانات سيتم ربط هذا الحقل به.
واجهة برمجة التطبيقات JPA لبيانات Spring
الخطوة التالية هي إنشاء واجهة برمجة التطبيقات 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 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
إلى أن الطريقة ستتم تنفيذها داخل العملية. سوف يهتم الربيع بإدارة العمليات التنفيذية.
فئة تحكم الربيع
الخطوة النهائية هي إنشاء فئة التحكم لتعريف واجهة برمجة التطبيق (APIs) للعالم الخارجي.
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
قم ببناء المشروع ونشره على خادم الويب المفضل لديك مثل تومكات. الصور التالية توضح الاستجابة لبعض استدعاءات واجهة برمجة التطبيق (APIs).
قراءة الكل في 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