У меня есть две сущности - 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 со своими свойствами. Не знаю, возможно ли это вообще.




Вам нужно изменить FetchType.LAZY на FetchType.EAGER, чтобы быть более устойчивым, когда Hibernate выполняет запрос, чтобы получить команду ..
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "first_team_id")
@JsonBackReference
private Team firstTeam;
По-прежнему говорит "firstTeamId": null :(
Итак, я предполагаю, что у вас проблема с отношениями при сохранении внешнего ключа.
Я исправил это, изменив метод 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;