2016-06-17 10 views
6

Jak poprawnie wystawiać leniwych załadowane wielu-wielu dziedzin, dzięki czemu użytkownicy mogą GET/PATCH/POST/DELETE wiele-wiele relacji podmiot w Spring REST danych?Pobieranie & Aktualizacja leniwych załadowane wiele-wiele pól w Spring Danych REST

Na przykład, biorąc pod uwagę Student jednostki i Teacher podmiot związany przez wiele do wielu relacji, z następującymi POJOs:

@Entity 
public class Teacher { // owner of bidirectional relationship 
    @Id 
    private int id; 
    private String name; 
    @ManyToMany(fetch = FetchType.LAZY) 
    @JoinTable(name = "teacher_student", 
      joinColumns = @JoinColumn(name = "teacher_id"), 
      inverseJoinColumns = @JoinColumn(name = "student_id")) 
    private Set<Student> students; 

    // Constructor, getters/setters... 
} 

@Entity 
public class Student { 
    @Id 
    private int id; 
    private String name; 
    @ManyToMany(mappedBy = "students", fetch = FetchType.LAZY) 
    private Set<Teacher> teachers; 

    // Constructor, getters/setters... 
} 

Podmioty podane są repozytoria:

@RepositoryRestResource(path = "teacher") 
public interface TeacherRepository extends CrudRepository<Teacher, int> {} 

// similar repository for student 

Kiedy wysłać a GET do localhost: 8080/nauczyciel, otrzymuję:

"_embedded": { 
    "teacher": [ 
     { 
     "name": "Bill Billie", 
     "_links": { 
      "self": { "href": "http://localhost:8080/teacher/1" }, 
      "teacher": { ... }, 
      "students": { "href": "http://localhost:8080/teacher/1/students" } 
     }}, 
     (more teachers here...) 
    ] 
} 
... 

ALE, kiedy spróbować GET do http://localhost:8080/teacher/1/students, otrzymuję 404 Not Found, chociaż nauczyciel „Bill Billie” robi mieć studenta związanego z nim w bazie danych.

Co ciekawe, jeśli zmienię FetchType do FetchType.EAGER, wszystko działa w porządku, a ja może wykonać oczekiwany GET, PATCH, itd. Co daje? Czy to może być błąd, czy coś spieprzyłem?

tl; dr Wiele-wiele relacji nie jest poprawnie wyeksponowanych z leniwym pobieraniem, ale działa dobrze z entuzjastycznym pobieraniem. Jak mogę leniwego pobierania do pracy z nim?

Edit: Jeśli ma to znaczenie, używam Wiosna 4.2.6 z wiosny Boot 1.3.5 i 2.4.1 OpenJPA jako mojego dostawcy JPA.

+0

Jest to prawdopodobnie dość skomplikowany problem; zwłaszcza, że ​​używasz OpenJPA zamiast powiedzieć, Hibernate, który jest prawdopodobnie lepiej znany.Jeśli podasz przykład działającego projektu, który demonstruje problem, masz większe szanse na rozwiązanie. –

+0

@WillFaithfull that's fair. Mogę dać taki strzał i spróbować mieć działający przykład, ale biorąc pod uwagę ilość zależności i niestandardową konfigurację, byłoby to trudne. Och, radości z niestandardowych potrzeb biznesowych. –

+0

Postaraj się zrobić jak najmniej minimalny przykład. Nie musi przypominać twojego modelu domeny, wystarczy odtworzyć problem. –

Odpowiedz

1

Hmm Nie jestem pewien, dlaczego nie jest to automatyczne pobieranie kogoś bardziej doświadczonego, ale można określić ręczne pobieranie z pobieraniem sprzężenia HQL dla każdego zapytania.

select x from X left join fetch x.y y 

Po zdobyciu tej pracy można przesłonić swoje oświadczenie get ze specjalnie utworzonego kontroler, jak opisano tutaj: Spring Data REST: Override repository method on the controller

Tylko inna opcja myślę może być warta stara jest dodawanie adnotacji @Lazy na swojej wiosenno Repozytorium danych.

+1

Tak, jestem prawie pewien, że mógłbym to uruchomić, jeśli ręcznie piszę wszystkie zapytania i przesłonię metody 'find', ale to przede wszystkim zniweczyłoby potrzebę używania Spring JPA i Data REST. Wolałbym zachować to w ostateczności. Aha i adnotacja '@ Lazy' też nie działa, niestety. –

+0

Oddałem nagrodę za pomocną odpowiedź, mimo że nie rozwiązało to dokładnie problemu, z którym miałem do czynienia. Nadal szukam więcej odpowiedzi. –

+0

Dzięki, gdy dostanę szansę, spróbuję przygotować projekt testowy i sprawdzić, czy mogę uruchomić jakieś debugowanie. –

1

Spróbuj wykonać transakcję RestResources.

Annotate z @Transactional

+0

Nie, nie działa. –

+0

Czy możesz tutaj wkleić fasolę TransactionManager? Tylko deklaracja fasoli z xml kontekstu –

0

Dodaj następującą zależność

<dependency> 
    <groupId>com.fasterxml.jackson.datatype</groupId> 
    <artifactId>jackson-datatype-hibernate4</artifactId> 
</dependency> 

Dodaj klasę konfiguracji.

@Configuration 
@EnableWebMvc 
public class WebConfig extends WebMvcConfigurerAdapter{ 


    public MappingJackson2HttpMessageConverter jacksonMessageConverter(){ 
     MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter(); 

     ObjectMapper mapper = new ObjectMapper(); 
     //Registering Hibernate4Module to support lazy objects 
     mapper.registerModule(new Hibernate4Module()); 

     messageConverter.setObjectMapper(mapper); 
     return messageConverter; 

    } 

    @Override 
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { 
     //Here we add our custom-configured HttpMessageConverter 
     converters.add(jacksonMessageConverter()); 
     super.configureMessageConverters(converters); 
    } 
} 
Powiązane problemy