Как получить объект Many To One, отображаемый в формате JSON

У меня есть две сущности - BaseEvent (спортивное мероприятие) и Team:

Команда:

@Entity
@Table(name = "teams")
@EntityListeners(AuditingEntityListener.class)
public class Team extends AbstractPersistable<Long> {
    private Long id;

    @NotBlank
    private String nameOfTeam;

    // we will create one transient field for leagueId
    @Transient
    private Long leagueId;

    @ManyToOne
    @JoinColumn(name = "league_id")
    @JsonBackReference
    private League league;

    // team promenlivata ot player
    @OneToMany(targetEntity = Player.class, mappedBy = "team", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JsonManagedReference
    private Set<Player> players = new HashSet<>();



    public Team(String nameOfTeam) {
        this.nameOfTeam = nameOfTeam;
    }

    public Team() {
    }


    public League getLeague() {
        return league;
    }

    public void setLeague(League league) {
        this.league = league;
    }

    public String getNameOfTeam() {
        return nameOfTeam;
    }

    public void setNameOfTeam(String nameOfTeam) {
        this.nameOfTeam = nameOfTeam;
    }

    public Long getLeagueId() {
        return leagueId;
    }

    public void setLeagueId(Long leagueId) {
        this.leagueId = leagueId;
    }

    public Set<Player> getPlayers() {
        return players;
    }

    public void setPlayers(Set<Player> players) {
        this.players = players;
    }

    @Override
    public Long getId() {
        return id;
    }

    @Override
    public void setId(Long id) {
        this.id = id;
    }
}

BaseEntity:

  @Entity
  @Table(name = "base_events")
  @EntityListeners(AuditingEntityListener.class)
  public class BaseEvent extends AbstractPersistable<Long> {

    private Long id;


    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy HH:mm:ss")
    @NotNull(message = "Start time cannot be empty")
    @Column
    private Date startTime;


    // we will create one transient field for teamId
    @Transient
    private Long firstTeamId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "first_team_id")
    @JsonBackReference
    private Team firstTeam;

    public BaseEvent(){}

    public BaseEvent(Date startTime) {
        this.startTime = startTime;
    }

    public Date getStartTime() {
        return startTime;
    }

    public void setStartTime(Date startTime) {
        this.startTime = startTime;
    }

    public Long getFirstTeamId() {
        return firstTeamId;
    }

    public void setFirstTeamId(Long firstTeamId) {
        this.firstTeamId = firstTeamId;
    }

    public Team getFirstTeam() {
        return firstTeam;
    }

    public void setFirstTeam(Team firstTeam) {
        this.firstTeam = firstTeam;
    }

    @Override
    public Long getId() {
        return id;
    }

    @Override
    public void setId(Long id) {
        this.id = id;
    }
}

У меня есть BaseEventDAO и BaseEventController:

// DATA ACCESS OBJECT
@Service
public class BaseEventDAO {

    @Autowired
    private BaseEventRepository baseEventRepository;

    /* to save an baseEvent in DB */

    public BaseEvent save(BaseEvent baseEvent) {
        return this.baseEventRepository.save(baseEvent);
    }

    /* search all baseEvents */

    public List<BaseEvent> findAll() {
        return this.baseEventRepository.findAll();
    }

    /* get an baseEvent */

    public BaseEvent findOne(Long baseEventId) {
        return this.baseEventRepository.findOne(baseEventId);
    }

    /* delete an baseEvent */

    public void delete(BaseEvent baseEvent) {
        this.baseEventRepository.delete(baseEvent);
    }
}

BaseEventController:

@RestController
@RequestMapping("/sportapp")
public class BaseEventController {

    @Autowired
    BaseEventDAO baseEventDAO;

    /* to save an baseEvent */
    @PostMapping("/baseEvent")
    public BaseEvent createBaseEvent(@Valid @RequestBody BaseEvent baseEvent) {
        return this.baseEventDAO.save(baseEvent);
    }

    /* get all baseEvents */
    @GetMapping("/baseEvents")
    public List<BaseEvent> getAllBaseEvents() {
        return this.baseEventDAO.findAll();
    }

    /* get an baseEvent by ID */
    @GetMapping("/baseEvents/{id}")
    public ResponseEntity<BaseEvent> getBaseEventById(@PathVariable(value = "id") Long baseEventId) {
        BaseEvent baseEvent = this.baseEventDAO.findOne(baseEventId);
        if (baseEvent == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok().body(baseEvent);
    }

    /* update an baseEvent */
    // TO DO SET THE NEW PROPERTIES OBJECT
    @PutMapping("/baseEvents/{id}")
    public ResponseEntity<BaseEvent> updateBaseEvent(@PathVariable(value = "id") Long baseEventId,
                                                     @Valid @RequestBody BaseEvent baseEventDetails) {
        BaseEvent baseEvent = this.baseEventDAO.findOne(baseEventId);
        if (baseEvent == null) {
            return ResponseEntity.notFound().build();
        }

        baseEvent.setStartTime(baseEventDetails.getStartTime());

        BaseEvent updateBaseEvent = this.baseEventDAO.save(baseEvent);
        return ResponseEntity.ok().body(updateBaseEvent);

    }

    /* delete an baseEvent */
    @DeleteMapping("/baseEvents/{id}")
    public ResponseEntity<BaseEvent> deleteBaseEvent(@PathVariable(value = "id") Long baseEventId) {

        BaseEvent baseEvent = this.baseEventDAO.findOne(baseEventId);
        if (baseEvent == null) {
            return ResponseEntity.notFound().build();
        }
        this.baseEventDAO.delete(baseEvent);

        return ResponseEntity.ok().build();
    }

}

Когда я выполняю PostMapping в Postman (/ baseEvent):

{
    "startTime" : "01/01/2019 22:22:22",
    "firstTeamId" : 1
}

Объект BaseEvent сохраняется в БД (ответ):

{
    "id": 2,
    "startTime": "01/01/2019 22:22:22",
    "firstTeamId": 1,
    "new": false
}

Но когда я выполняю GetMapping, чтобы получить этот объект (/ baseEvents / 2), вот ответ:

{
    "id": 2,
    "startTime": "01/01/2019 22:22:22",
    "firstTeamId": null,
    "new": false
}

Я думаю, что мне нужно:

{
"id": 2,
"startTime": "01/01/2019 22:22:22",
"firstTeamId": 1,
"firstTeam" : {
    "id" : 1,
    "nameOfTeam": "Barca",
    "leagueId": null,
    "players": [],
    "new": false
},
"new": false
}

У меня две проблемы, которые я не могу решить. Первый ("firstTeamId": null) должен указывать 1, а не "null". Во-вторых, я не получаю сопоставленный объект Team (firstTeam), поэтому интерфейс может его использовать.

Первый раз, когда задаете вопрос, извините, пожалуйста, и скажите, если вам нужны более подробные сведения.

@JBNizet Я читал, что JsonBackReference - это двусторонняя связь между полями, поэтому я удалил ее. Но когда я делаю Post, я хочу указать идентификатор firstTeam по идентификатору (а не по объекту JSON Team). И когда я нажимаю Get, я хочу видеть firstTeam как объект JSON со своими свойствами. Не знаю, возможно ли это вообще.

I.Stanev 11.11.2018 21:44
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
2 418
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам нужно изменить FetchType.LAZY на FetchType.EAGER, чтобы быть более устойчивым, когда Hibernate выполняет запрос, чтобы получить команду ..

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "first_team_id")
@JsonBackReference
private Team firstTeam;

По-прежнему говорит "firstTeamId": null :(

I.Stanev 12.11.2018 12:13

Итак, я предполагаю, что у вас проблема с отношениями при сохранении внешнего ключа.

Jonathan JOhx 12.11.2018 17:13
Ответ принят как подходящий

Я исправил это, изменив метод BaseEventController Post:

@Autowired
BaseEventDAO baseEventDAO;


@Autowired
TeamDAO teamDAO;

/* to save an baseEvent */
@PostMapping("/baseEvent")
public BaseEvent createBaseEvent(@Valid @RequestBody BaseEvent baseEvent) {
    Team team = this.teamDAO.findOne(baseEvent.getFirstTeamId());
    BaseEvent event = new BaseEvent();
    event.setStartTime(baseEvent.getStartTime());
    event.setFirstTeam(team);
    event.setFirstTeamId(baseEvent.getFirstTeamId());
    return this.baseEventDAO.save(event);
}

И удалил @Transient из firstTeamId и изменил столбец соединения:

@Column(name = "first_team_id")
 private Long firstTeamId;

@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "team_id", referencedColumnName = "id")
private Team firstTeam;

Другие вопросы по теме