В предыдущей серии статей я рассказывал о том, как создать сервис 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@LocalBeanpublic 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" } } ] }] |