Статьи

Двунаправленные отношения с Джексоном в веб-сервисах REST в WildFly

Это пример  двунаправленной связи  между объектами Java в веб-службе REST с  API Джексона .

1. Предположим, у нас есть двунаправленные отношения между двумя объектами: Родителем и Ребенком.

2. Использование MySQL для создания файла схемы SQL для этих двух таблиц.

DROP SCHEMA IF EXISTS `bidirectional_schema` ;
CREATE SCHEMA IF NOT EXISTS `bidirectional_schema` DEFAULT CHARACTER SET utf8 ;
USE `bidirectional_schema` ;

-- -----------------------------------------------------
-- Table `bidirectional_schema`.`PARENT`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `bidirectional_schema`.`PARENT` ;

CREATE  TABLE IF NOT EXISTS `bidirectional_schema`.`PARENT` (
  `PARENT_ID` INT NOT NULL ,
  `PARENT_CONTENT` VARCHAR(45) NULL ,
  PRIMARY KEY (`PARENT_ID`) )
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `bidirectional_schema`.`CHILD`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `bidirectional_schema`.`CHILD` ;

CREATE  TABLE IF NOT EXISTS `bidirectional_schema`.`CHILD` (
  `CHILD_ID` INT NOT NULL ,
  `CHILD_CONTENT` VARCHAR(45) NULL ,
  `PARENT_PARENT_ID` INT NOT NULL ,
  PRIMARY KEY (`CHILD_ID`) ,
  INDEX `fk_CHILD_PARENT_idx` (`PARENT_PARENT_ID` ASC) ,
  CONSTRAINT `fk_CHILD_PARENT`
    FOREIGN KEY (`PARENT_PARENT_ID` )
    REFERENCES `bidirectional_schema`.`PARENT` (`PARENT_ID` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

3- Затем мы вставим некоторые данные в эти две таблицы с помощью этих операторов вставки:

INSERT INTO `bidirectional_schema`.`parent` (`PARENT_ID`, `PARENT_CONTENT`) VALUES ('1', 'First Parent');
INSERT INTO `bidirectional_schema`.`child` (`CHILD_ID`, `CHILD_CONTENT`, `PARENT_PARENT_ID`) VALUES ('1', 'First Child', '1');
INSERT INTO `bidirectional_schema`.`child` (`CHILD_ID`, `CHILD_CONTENT`, `PARENT_PARENT_ID`) VALUES ('2', 'Second Child', '1');

4. Зависимости Maven для API Джексона, необходимые для этого примера.

<dependency>
 <groupid>com.fasterxml.jackson.core</groupid>
 <artifactid>jackson-annotations</artifactid>
 <version>2.5.2</version>
</dependency>
<dependency>
 <groupid>com.fasterxml.jackson.core</groupid>
 <artifactid>jackson-core</artifactid>
 <version>2.5.2</version>
</dependency>
<dependency>
 <groupid>com.fasterxml.jackson.core</groupid>
 <artifactid>jackson-databind</artifactid>
 <version>2.5.2</version>
</dependency>

Также по этой ссылке вы можете получить требуемые зависимости Java EE.
https://wikis.oracle.com/display/GlassFish/Java+EE+7+Maven+Coordinates
5 — Использование Eclipse для создания сущностей из приведенных выше таблиц.
Файл -> Создать -> Другое, затем в мастере выберите JPA Entities из таблиц. Появится мастер для создания соединения с уже созданной схемой. Затем выберите две таблицы: дочернюю и родительскую. Наконец убедитесь, что «Список сгенерированных классов в persistence.xml». Вы можете продолжить и следовать настройкам по умолчанию, но я выбрал настройки отображения как показано ниже:



6- В файле persistence.xml нет ничего особенного. Но есть два момента, которые следует учитывать. Во-первых, я не указывал поставщика постоянства, поскольку я склонен использовать WildFly, поэтому приложение будет использовать поставщик постоянства по умолчанию, который называется Hibernate. Во-вторых, я создал источник данных в WildFly, чтобы его можно было использовать для подключения к нашей схеме. В-третьих, я использовал EclipseLink, поэтому я использую этот JPA-провайдер org.eclipse.persistence.jpa.PersistenceProvider. Проверьте  этот  пост, чтобы указать WildFly на EclipseLink.

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
 <persistence-unit name="BidirectionalPU">
     <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
     <jta-data-source>java:jboss/datasources/Bidirectional_DataSource</jta-data-source>
     <class>com.ithinkisink.entity.Child</class>
     <class>com.ithinkisink.entity.Parent</class>
 </persistence-unit>
</persistence>

7. Первый класс, который мы реализуем, — это класс ApplicationConfiguration, который будет указывать на родительский путь наших будущих служб REST.

package com.ithinkisink;

import javax.inject.Singleton;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

/**
 * 
 * @author Belal
 *
 */
@Singleton
@ApplicationPath("rest")
public class ApplicationConfiguration extends Application {
}

8. Затем мы создадим класс MyService, который будет иметь два веб-сервиса REST. Первый извлечет родителя с выбранными детьми. Второй вариант противоположен этому и будет извлекать ребенка с его родителями.

package com.ithinkisink.service;

package com.ithinkisink.service;

import javax.ejb.EJB;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import com.ithinkisink.entity.Child;
import com.ithinkisink.entity.Parent;

/**
 * 
 * @author Belal
 *
 */
@Path("MyService")
public class MyService {

 @EJB
 MyServiceDAO myServiceDAO;

 @GET
 @Path("/retrieveParentWithChildren")
 @Produces(MediaType.APPLICATION_JSON)
 public Parent retrieveParentWithChildren() {
  return myServiceDAO.retrieveParentWithChildren();
 }

 @GET
 @Path("/retrieveChildWithParent")
 @Produces(MediaType.APPLICATION_JSON)
 public Child retrieveChildWithParent() {
  return myServiceDAO.retrieveChildWithParent();
 }
}

9. Затем мы создадим ServiceDAO и заметим, что EntityManager внедряется с подключением к постоянному модулю, который мы уже определили в файле persistence.xml. Я передал название единицы персистентности, чтобы прояснить этот момент. Но вы можете просто использовать аннотацию @PersistenceContext без указания атрибута unitName, тогда она будет использовать наш модуль постоянства, поскольку в нашем приложении не определено никакого другого модуля постоянства.

package com.ithinkisink.service;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import com.ithinkisink.entity.Child;
import com.ithinkisink.entity.Parent;

@Stateless
public class MyServiceDAO {

 @PersistenceContext(unitName="BidirectionalPU")
 protected EntityManager entityManager;

 public Parent retrieveParentWithChildren() {
  int parentId = 1;
  Query q = entityManager.createQuery("SELECT p FROM " + "Parent " + "p JOIN FETCH p.childs WHERE p.parentId = :parentId ");
  q.setParameter("parentId", parentId);
  return (q.getResultList().size() > 0) ? (Parent) q.getResultList().get(0) : null;
 }

 public Child retrieveChildWithParent() {
  int childId = 1;
  Query q = entityManager.createQuery("SELECT c FROM " + "Child " + "c JOIN FETCH c.parent WHERE c.childId = :childId ");
  q.setParameter("childId", childId);
  return (q.getResultList().size() > 0) ? (Child) q.getResultList().get(0) : null;
 }
}

10. Теперь, когда наше приложение готово к тестированию, добавим его на сервер WildFly. Тогда запуск сервера должен быть успешным.
11. Для простоты я использовал  Postman  для тестирования запущенных веб-сервисов REST. Итак, ниже приведены скриншоты из результатов на Почтальоне. Вы можете найти полный пример на моем Github по этой ссылке: https://github.com/belalgalal/Blogging/tree/master/BidirectionalRESTJson