У меня есть пользователи и точки.Каждый пользователь может добавить в избранное несколько точек, а несколько точек могут быть добавлены в список.
Я написал API отдыха, который может отображать пятна в моей базе данных H2.
package spring.backend.springmvcrest.controllers;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import spring.backend.springmvcrest.model.Spot;
import spring.backend.springmvcrest.services.SpotService;
import java.util.List;
@RestController
@RequestMapping(SpotController.BASE_URL)
public class SpotController {
public static final String BASE_URL = "/api/spots";
private final SpotService spotService;
public SpotController(SpotService spotService) {
this.spotService = spotService;
}
@GetMapping
public List<Spot> getAllSpots(){
return spotService.findAllSpots();
}
@GetMapping("/{id}")
public Spot getSpotById(@PathVariable Long id){
return spotService.findSpotById(id);
}
}
package spring.backend.springmvcrest.services;
import org.springframework.stereotype.Service;
import spring.backend.springmvcrest.model.Spot;
import spring.backend.springmvcrest.repositories.SpotRepository;
import java.util.List;
@Service
public class SpotServiceImpl implements SpotService {
private final SpotRepository spotRepository;
public SpotServiceImpl(SpotRepository spotRepository) {
this.spotRepository = spotRepository;
}
@Override
public Spot findSpotById(Long id) {
return spotRepository.findById(id).get();
}
@Override
public List<Spot> findAllSpots() {
return spotRepository.findAll();
}
}
package spring.backend.springmvcrest.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import spring.backend.springmvcrest.model.Spot;
@Repository
public interface SpotRepository extends JpaRepository<Spot, Long> {
}
package spring.backend.springmvcrest.model;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Data
@Entity
@EqualsAndHashCode(exclude = "users")
public class Spot {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private float longitude;
private float latitude;
private float wind;
@ManyToOne
@JsonManagedReference
private Country country;
private String month;
@ManyToMany
@JoinTable(name = "favorites",
joinColumns = @JoinColumn(name = "spot_id"),
inverseJoinColumns = @JoinColumn(name = "user_id"))
@JsonBackReference
private Set<User> users = new HashSet<>();
}
Это работает нормально и возвращает все места, которые есть в моей базе данных H2 (доказывая, что места есть)
Теперь я хочу создать любимую запись для пользователя.Поэтому мне нужен spot_id user_id и сервис, который может сделать это + контроллер.Итак, я написал это:
package spring.backend.springmvcrest.controllers;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import spring.backend.springmvcrest.model.User;
import spring.backend.springmvcrest.services.FavoriteService;
import java.util.Map;
@RestController
@RequestMapping(FavoriteController.BASE_URL)
public class FavoriteController {
public static final String BASE_URL = "/api/favorites/spots";
private final FavoriteService favoriteService;
public FavoriteController(FavoriteService favoriteService) {
this.favoriteService = favoriteService;
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public User create(@RequestBody Map<String, Object> body){
Long user_id = Long.valueOf(body.get("user_id").toString()).longValue();
Long spot_id = Long.valueOf(body.get("spot_id").toString()).longValue();
return favoriteService.create(user_id, spot_id);
}
}
package spring.backend.springmvcrest.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import spring.backend.springmvcrest.model.Spot;
import spring.backend.springmvcrest.model.User;
import spring.backend.springmvcrest.repositories.SpotRepository;
import spring.backend.springmvcrest.repositories.UserRepository;
@Service
public class FavoriteServiceImpl implements FavoriteService {
private final UserRepository userRepository;
private final SpotRepository spotRepository;
public FavoriteServiceImpl(UserRepository userRepository, SpotRepository spotRepository) {
this.userRepository = userRepository;
this.spotRepository = spotRepository;
System.out.println("dwadwadwadwa");
System.out.println(this.userRepository);
}
@Override
public User create(Long user_id, Long spot_id) {
System.out.println("balalalalala");
System.out.println(user_id);
System.out.println(spot_id);
System.out.println(this.userRepository);
System.out.println(spotRepository.findAll().toString());
System.out.println(userRepository.findAll().toString());
System.out.println("balalalalala");
User user = userRepository.findById(user_id).get();
System.out.println(user);
Spot spot = spotRepository.findById(spot_id).get();
//System.out.println(spot);
System.out.println(user.getSpots());
user.getSpots().add(spot);
//spot.getUsers().add(user);
userRepository.save(user);
//spotRepository.save(spot);
return user;
}
@Override
public void delete(Long user_id, Long spot_id) {
}
}
Теперь в этом сервисе, даже если все идентично предыдущему сервису, я получаю нулевую ошибку, когда я выполняю spotRepository.findAll () (или любую другую операцию SQL)
Полный код можно найти здесь: https://github.com/lucianacimbir/spring-mvc-rest/tree/add-spots-delete-post
Ошибка:
2019-03-09 23:39:06.026 ERROR 5690 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.StackOverflowError] with root cause
java.lang.StackOverflowError: null
at org.h2.command.Parser.readTerm(Parser.java:3093) ~[h2-1.4.197.jar:1.4.197]
at org.h2.command.Parser.readFactor(Parser.java:2587) ~[h2-1.4.197.jar:1.4.197]
at org.h2.command.Parser.readSum(Parser.java:2574) ~[h2-1.4.197.jar:1.4.197]
at org.h2.command.Parser.readConcat(Parser.java:2544) ~[h2-1.4.197.jar:1.4.197]
at org.h2.command.Parser.readCondition(Parser.java:2370) ~[h2-1.4.197.jar:1.4.197]
Любая подсказка, почему это может вызвать ошибку?Это приложение Spring 5.
РЕДАКТИРОВАНИЕ 1: Кажется, что spotRepository.findById возвращает spot_instance.toString () вместо экземпляра Spot.ПОЧЕМУ?!
PS Я новичок, поэтому любые советы о том, как лучше организовать код, приветствуются.