Статьи

Представляем EclipseLink JPA-RS

В предыдущей серии статей я рассказывал о том, как создать сервис JAX-RS, который использовал JPA для уровня персистентности. EclipseLink содержит компонент, называемый JPA-RS, который можно использовать для простого и автоматического представления единицы сохраняемости в качестве службы RESTful (которая поддерживает сообщения XML и JSON). MOXy обеспечивает привязку XML и JSON для JPA-RS, и такие вещи, как двунаправленные сопоставления, автоматически сопоставляются для вас. В другом посте я расскажу, как MOXy можно использовать для настройки сообщений, показанных в этом примере.

Я буду использовать модель JPA, которую я создал в постах ниже:

Упаковка / Развертывание

Использование JPA-RS — это простой вопрос упаковки. Мы создадим WAR, содержащий нашу модель JPA в JAR, JAR JPA-RS и простой сессионный компонент для инициализации нашей модели JPA. Для этого примера я использую продвинутую сборку GlassFish 4.0, которая содержит EclipseLink 2.5.

CustomerJPARS.war

  • WEB-INF
    • классы
      • организация
        • пример
          • EJB
            • PersistenceWeaverBean.class
    • 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, которую мы определили в следующем посте:

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": {
                "method": "application/json",
                "rel": "Address"
            }
        },
        {
            "_link": {
                "method": "application/json",
                "rel": "PhoneNumber"
            }
        },
        {
            "_link": {
                "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",
            "rel": "find"
        },
        {
            "method": "put",
            "rel": "persist"
        },
        {
            "method": "post",
            "rel": "update"
        },
        {
            "method": "delete",
            "rel": "delete"
        }
    ],
    "queries": [
        {
            "queryName": "findCustomersByCity",
            "returnTypes": [
                "Customer"
            ],
            "linkTemplate": {
                "method": "get",
                "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": {
                    "rel": "address"
                }
            },
            {
                "_link": {
                    "rel": "phoneNumbers"
                }
            }
        ],
        "address": {
            "_link": {
                "method": "GET",
                "rel": "self"
            }
        },
        "phoneNumbers": [
            {
                "_link": {
                    "method": "GET",
                    "rel": "self"
                }
            },
            {
                "_link": {
                    "method": "GET",
                    "rel": "self"
                }
            }
        ]
    }
]

Ссылка: Представляем EclipseLink JPA-RS от нашего партнера по JCG Блэза Дафана в блоге Java XML & JSON Binding .