В предыдущей серии статей я рассказывал о том, как создать сервис JAX-RS, который использовал JPA для уровня персистентности. EclipseLink содержит компонент, называемый JPA-RS, который можно использовать для простого и автоматического представления единицы сохраняемости в качестве службы RESTful (которая поддерживает сообщения XML и JSON). MOXy обеспечивает привязку XML и JSON для JPA-RS, и такие вещи, как двунаправленные сопоставления, автоматически сопоставляются для вас. В другом посте я расскажу, как MOXy можно использовать для настройки сообщений, показанных в этом примере.
Я буду использовать модель JPA, которую я создал в постах ниже:
- Часть 1 — База данных
- Часть 2 — Отображение базы данных на объекты JPA
Упаковка / Развертывание
Использование JPA-RS — это простой вопрос упаковки. Мы создадим WAR, содержащий нашу модель JPA в JAR, JAR JPA-RS и простой сессионный компонент для инициализации нашей модели JPA. Для этого примера я использую продвинутую сборку GlassFish 4.0, которая содержит EclipseLink 2.5.
CustomerJPARS.war
- WEB-INF
- классы
- организация
- пример
- EJB
- PersistenceWeaverBean.class
- EJB
- пример
- организация
- Lib
- CustomerJPA.jar
- org.eclipse.persistence.jpars_2.5.0.qualifier.jar
- классы
- META-INF
- MANIFEST.MF
PersistenceWeaverBean
JPA-RS требует, чтобы объекты JPA были инициализированы. Для этого мы создадим простой сессионный компонент.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
package org.example.ejb; import javax.ejb.*; import javax.persistence.*; @Startup @Singleton @LocalBean public class PersistenceWeaverBean { @SuppressWarnings ( "unused" ) @PersistenceUnit (unitName = "CustomerService" ) private EntityManagerFactory emf; } |
CustomerJPA.jar
Этот JAR содержит модель JPA, которую мы определили в следующем посте:
- Часть 2 — Отображение базы данных на объекты JPA
org.eclipse.persistence.jpars_2.5.0.qualifier.jar
Это JAR-файл JPA-RS, который поставляется из установки EclipseLink:
1
|
<ECLIPSELINK_HOME> /jlib/jpa/org .eclipse.persistence.jpars_2.5.0.qualifier.jar |
Что я могу сделать с моим сервисом? (Метаданные службы)
Как только мы развернем WAR, наш сервис активен. Мы можем выполнить GET, чтобы увидеть метаданные для нашего сервиса.
GET (приложение / XML или приложение / JSON)
URI для получения метаданных для службы имеет следующий формат:
1
|
http: // {Server}/{Application} /persistence/v1 .0/{PersistenceUnit} /metadata |
Ниже приведен URI для нашего примера:
1
|
http: //localhost :8080 /CustomerJPARS/persistence/v1 .0 /CustomerService/metadata |
отклик
Ниже приведены метаданные для нашего сервиса. Помимо имени единицы персистентности, мы видим ссылки на метаданные для каждого из объектов в нашей модели JPA. Далее мы более подробно рассмотрим сущность Customer .
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
{ "persistenceUnitName" : "CustomerService" , "types" : [ { "_link" : { "href" : "http://localhost:8080/CustomerJPARS/persistence/v1.0/CustomerService/metadata/entity/Address" , "method" : "application/json" , "rel" : "Address" } }, { "_link" : { "href" : "http://localhost:8080/CustomerJPARS/persistence/v1.0/CustomerService/metadata/entity/PhoneNumber" , "method" : "application/json" , "rel" : "PhoneNumber" } }, { "_link" : { "href" : "http://localhost:8080/CustomerJPARS/persistence/v1.0/CustomerService/metadata/entity/Customer" , "method" : "application/json" , "rel" : "Customer" } } ] } |
Что я могу сделать с сущностью? (Метаданные сущности)
Если мы перейдем по ссылке для одной из организаций, то получим следующую информацию:
- Атрибуты сущностей.
- Операции CRUD, которые мы можем выполнять над объектом.
- Именованные запросы, которые мы можем выполнить на объекте.
GET (приложение / XML или приложение / JSON)
URI для получения метаданных для объекта имеет следующий формат:
1
|
http: // {Server}/{Application} /persistence/v1 .0/{PersistenceUnit /metadata/entity/ {Entity} |
Ниже приведен URI для получения метаданных для сущности Customer :
1
|
http: //localhost :8080 /CustomerJPARS/persistence/v1 .0 /CustomerService/metadata/entity/Customer |
отклик
Ниже приведены метаданные для объекта « Клиент» . Мы подробнее рассмотрим операцию POST (строки 37–39) и именованный запрос (строки 49–58).
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
{ "name" : "Customer" , "attributes" : [ { "name" : "id" , "type" : "long" }, { "name" : "firstName" , "type" : "String" }, { "name" : "lastName" , "type" : "String" }, { "name" : "address" , "type" : "Address" }, { "name" : "phoneNumbers" , "type" : "Set<PhoneNumber>" } ], "linkTemplates" : [ { "method" : "get" , "href" : "http://localhost:8080/CustomerJPARS/persistence/v1.0/CustomerService/entity/Customer/{primaryKey}" , "rel" : "find" }, { "method" : "put" , "rel" : "persist" }, { "method" : "post" , "rel" : "update" }, { "method" : "delete" , "href" : "http://localhost:8080/CustomerJPARS/persistence/v1.0/CustomerService/entity/Customer/{primaryKey}" , "rel" : "delete" } ], "queries" : [ { "queryName" : "findCustomersByCity" , "returnTypes" : [ "Customer" ], "linkTemplate" : { "method" : "get" , "href" : "http://localhost:8080/CustomerJPARS/persistence/v1.0/CustomerService/query/findCustomersByCity;city={city}" , "rel" : "execute" }, "jpql" : "SELECT c FROM Customer c WHERE c.address.city = :city" } ] } |
Сохранение сущности
Мы будем использовать операцию POST для создания нового экземпляра объекта Customer .
POST (приложение / XML или приложение / JSON)
URI для создания объекта имеет следующий формат:
1
|
http: // {Server}/{Application} /persistence/v1 .0/{PersistenceUnit} /entity/ {Entity} |
Ниже приведен URI для создания экземпляра Customer :
1
|
http: //localhost :8080 /CustomerJPARS/persistence/v1 .0 /CustomerService/entity/Customer |
Запрос
Ниже приведено JSON-представление данных наших клиентов, которые мы опубликуем в вышеуказанном URI:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
{ "id" : 1 , "firstName" : "Jane" , "lastName" : "Doe" , "address" : { "id" : 1 , "street" : "1 A Street" , "city" : "Any Town" }, "phoneNumbers" : [{ "id" : 2 , "type" : "work" , "num" : "555-1111" }, { "id" : 3 , "type" : "home" , "num" : "555-2222" }] } |
Выполнение запроса
JPA-RS автоматически создает URI для каждого из именованных запросов, которые мы определили в нашей модели JPA:
GET (приложение / XML или приложение / JSON)
URI для выполнения именованного запроса имеет следующий формат:
1
|
http: // {Server}/{Application} /persistence/v1 .0/{PersistenceUnit} /query/ {NamedQuery;Parameters} |
Ниже мы вызовем именованный запрос findCustomersByCity, чтобы найти всех клиентов из любого города .
1
|
http: //localhost :8080 /CustomerJPARS/persistence/v1 .0 /CustomerService/query/findCustomersByCity ;city=Any%20Town |
отклик
Ниже приведен результат вызова именованного запроса. Мы можем видеть, что отношения между сущностями представлены в виде ссылок. Вы выполняете GET по ссылке, чтобы получить ссылочные данные.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
[ { "firstName" : "Jane" , "id" : 1 , "lastName" : "Doe" , "_relationships" : [ { "_link" : { "href" : "http://localhost:8080/CustomerJPARS/persistence/v1.0/CustomerService/entity/Customer/1/address" , "rel" : "address" } }, { "_link" : { "href" : "http://localhost:8080/CustomerJPARS/persistence/v1.0/CustomerService/entity/Customer/1/phoneNumbers" , "rel" : "phoneNumbers" } } ], "address" : { "_link" : { "method" : "GET" , "rel" : "self" } }, "phoneNumbers" : [ { "_link" : { "href" : "http://localhost:8080/CustomerJPARS/persistence/v1.0/CustomerService/entity/PhoneNumber/3" , "method" : "GET" , "rel" : "self" } }, { "_link" : { "href" : "http://localhost:8080/CustomerJPARS/persistence/v1.0/CustomerService/entity/PhoneNumber/2" , "method" : "GET" , "rel" : "self" } } ] } ] |