2016-06-17 41 views
6

如何正確暴露延遲加載多對多的領域很多,很多領域,使用戶可以GET/PATCH/POST/DELETE多對多實體關係, Spring Data REST?擷取及更新延遲加載在Spring數據REST

例如,給定一個Student實體,並通過許多勢必一對多的關係,具有以下的POJOs Teacher實體:

@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... 
} 

的單位給出的數據存儲:

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

// similar repository for student 

當我送a GET to localhost:8080/teacher,我得到:

"_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...) 
    ] 
} 
... 

,當我嘗試GEThttp://localhost:8080/teacher/1/students,我得到一個404未找到,即使老師「比爾比利」 確實有他在數據庫相關聯的學生。

有趣的是,如果我改變FetchTypeFetchType.EAGER,一切工作正常,我可以執行預期GETPATCH等是怎麼回事?這可能是一個錯誤,或者我搞砸了嗎?

TL;博士多對多的關係不正確地延遲抓取裸露,而是用預先抓取做工精細。我怎樣才能獲得懶惰提取使用它?

編輯:如果它的事項,我使用Spring 4.2.6與Spring 1.3.5引導,和OpenJPA 2.4.1作爲我JPA提供商。

+0

這可能是一個相當複雜的問題;特別是因爲你正在使用的OpenJPA,而不是說,休眠,這可能是更出名。如果您提供了一個演示問題的示例項目,那麼您更有可能獲得解決方案。 –

+0

@ WillFaithfull這是公平的。我可以嘗試一下,嘗試一個有效的例子,儘管考慮到大量的依賴關係和自定義配置,這將是具有挑戰性的。哦,定製業務需求的樂趣。 –

+0

儘量讓最小的例子成爲可能。它不需要類似於您的域模型,只是重現問題。 –

回答

1

嗯,我不知道爲什麼它是不會自動取更有經驗的人將不得不問,但你可以指定一個手動取得與HQL的連接抓取每個查詢。

select x from X left join fetch x.y y 

得到這個工作,你可以用一個專門創建控制器覆蓋您的GET語句如下描述後:Spring Data REST: Override repository method on the controller

唯一的選擇,我認爲可能是值得嘗試的是將你的春季 - 一個@Lazy註釋數據存儲庫。

+1

是的,我敢肯定,如果我手動編寫所有查詢並重寫'find'方法,我就可以實現它的工作,但這首先會挫敗使用Spring JPA和Data REST的重點。我寧願保留這個作爲最後的手段。哦,不幸的是,'@ Lazy'註解也不起作用。 –

+0

儘管沒有完全解決我面臨的問題,但我已經爲您提供了有益的回覆,因此我已授予您賞金。仍在尋找更多的答案。 –

+0

謝謝,當我有機會時,我會嘗試設置一個測試項目,看看我是否可以運行一些調試。 –

1

請嘗試將RestResources事務。

標註與@Transactional

+0

不,不起作用。 –

+0

你可以在這裏粘貼你的TransactionManager bean。只需從上下文xml的bean聲明 –

0

添加以下依賴

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

添加配置類。

@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); 
    } 
}