Spring Data REST'te bir @OneToMany alt kaynak ilişkilendirmesi POSTing


103

Şu anda Spring Data REST kullanan bir Spring Boot uygulamam var. Bir etki alanı varlık var Postsahiptir @OneToMany, başka bir etki alanı varlığa ilişkiyi Comment. Bu sınıflar aşağıdaki şekilde yapılandırılmıştır:

Post.java:

@Entity
public class Post {

    @Id
    @GeneratedValue
    private long id;
    private String author;
    private String content;
    private String title;

    @OneToMany
    private List<Comment> comments;

    // Standard getters and setters...
}

Comment.java:

@Entity
public class Comment {

    @Id
    @GeneratedValue
    private long id;
    private String author;
    private String content;

    @ManyToOne
    private Post post;

    // Standard getters and setters...
}

Spring Data REST JPA depoları şunların temel uygulamalarıdır CrudRepository:

PostRepository.java:

public interface PostRepository extends CrudRepository<Post, Long> { }

CommentRepository.java:

public interface CommentRepository extends CrudRepository<Comment, Long> { }

Uygulama giriş noktası, standart, basit bir Spring Boot uygulamasıdır. Her şey yapılandırılmış stok.

Application.java

@Configuration
@EnableJpaRepositories
@Import(RepositoryRestMvcConfiguration.class)
@EnableAutoConfiguration
public class Application {

    public static void main(final String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Görünüşe göre her şey doğru çalışıyor. Uygulamayı çalıştırdığımda, her şey düzgün çalışıyor gibi görünüyor. Beğenmek için yeni bir Gönderi nesnesi POST yapabilirim http://localhost:8080/posts:

Vücut: {"author":"testAuthor", "title":"test", "content":"hello world"}

Sonuç http://localhost:8080/posts/1:

{
    "author": "testAuthor",
    "content": "hello world",
    "title": "test",
    "_links": {
        "self": {
            "href": "http://localhost:8080/posts/1"
        },
        "comments": {
            "href": "http://localhost:8080/posts/1/comments"
        }
    }
}

Ancak, bir GET gerçekleştirdiğimde , dönen http://localhost:8080/posts/1/commentsboş bir nesne {}alıyorum ve aynı URI'ye bir yorum göndermeye çalışırsam, HTTP 405 Yöntemine İzin Verilmiyor.

Bir Commentkaynak oluşturmanın ve bununla ilişkilendirmenin doğru yolu nedir Post? Mümkünse doğrudan adresine POST göndermekten kaçınmak istiyorum http://localhost:8080/comments.


9
7 gün sonra ve hala şans değil. Bu davranışı çalıştırmanın bir yolunu bilen varsa, lütfen bana bildirin. Teşekkürler!
ccampo

@RepositoryRestResource veya bir denetleyici kullanıyor musunuz? O kodu görmek de faydalı olacaktır.
Magnus Lassi

Yanıtlar:


47

Önce yorumu göndermelisiniz ve yorumu gönderirken bir ilişkilendirme gönderileri varlığı oluşturabilirsiniz.

Aşağıdaki gibi görünmelidir:

http://{server:port}/comment METHOD:POST

{"author":"abc","content":"PQROHSFHFSHOFSHOSF", "post":"http://{server:port}/post/1"}

ve mükemmel bir şekilde çalışacak.


2
Bu benim için çalıştı. Sadece author.postyazılabilir olduğundan emin olun (örneğin bir ayarlayıcı veya @JsonValueaçıklama
alarak

1
Bu, yorumu bir gönderiden diğerine taşırken olduğu gibi bir yama isteğiyle de çalışmalı mı?
aycanadal

2
Bu benim (büyük ölçüde) tercih ettiğim yaklaşımım olurdu, ancak benim için işe yaramıyor gibi görünüyor. :( Yorum'u oluşturur, ancak çözüm tablosunda (POST_COMMENTS) satırı oluşturmaz. Nasıl çözüleceğine dair herhangi bir öneriniz var mı?
banncee

3
Bir yerin bir Adrese sahip olması ve bir adresin bir Mekân ile ilişkilendirilmesi ZORUNLU olduğu Mekan ve Adres varlıkları gibi bir senaryo için yaklaşım ne olmalıdır? Yani ... hiçbir şeye atanamayacak öksüz bir adres oluşturmaktan kaçınmak için mi? Belki yanılıyorum, ancak istemci uygulaması veri tabanında tutarlılığı sağlamaktan ASLA sorumlu olmamalıdır. İstemci uygulamasının bir Adres oluşturmasına ve ardından kesinlikle bir Mekana atamasına güvenemiyorum. Tutarsızlığı önlemek için asıl kaynağın oluşturulmasıyla alt kaynağı (bu durumda Adres varlığı) POST yapmanın bir yolu var mı?
apostrophedottilde

2
Bunu yapmaya çalışıyorum ( buraya bakın ), ancak bir nedenden ötürü sadece kaynak yaratıldı, dernek değil.
ekran adı

55

URI sonrası ve dolayısıyla ilişkilendirme kaynağının URI'sini zaten keşfettiğinizi varsayarsak ( $association_uriaşağıda olduğu kabul edilir ), genellikle şu adımları atar:

  1. Yorumları yöneten koleksiyon kaynağını keşfedin:

    curl -X GET http://localhost:8080
    
    200 OK
    { _links : {
        comments : { href : "…" },
        posts :  { href : "…" }
      }
    }
    
  2. Kaynağa giden commentsbağlantıyı ve POSTverilerinizi takip edin :

    curl -X POST -H "Content-Type: application/json" $url 
    {  // your payload // … }
    
    201 Created
    Location: $comment_url
    
  3. PUTDernek URI'sına bir yayınlayarak yorumu gönderiye atayın .

    curl -X PUT -H "Content-Type: text/uri-list" $association_url
    $comment_url
    
    204 No Content
    

Son adımda, spesifikasyonuna göre text/uri-list, aynı anda birden çok yorum atamak için satır sonu ile ayrılmış yorumları tanımlayan birden çok URI gönderebileceğinizi unutmayın.

Genel tasarım kararları hakkında birkaç not daha. Bir post / yorumlar, örneğin, genellikle bir geri referans önleyeceğini aracı, bir agrega için, büyük bir örnek Commentiçin Postve aynı zamanda önlemek CommentRepositorytamamen. Yorumların kendi başlarına bir yaşam döngüsü yoksa (genellikle kompozisyon tarzı bir ilişkide bulunmazlar) yorumların doğrudan satır içinde işlenmesini tercih edersiniz ve yorum ekleme ve çıkarma işleminin tamamı daha ziyade kullanılarak ele alınabilir. JSON Yaması . Spring Data REST, gelecek sürüm 2.2 için en son sürüm adayına bunun için destek ekledi .


4
Buraya aşağıdan gelen seçmenlerden ilgi, oyların nedeninin ne olduğu;).
Oliver Drotbohm

3
Aşağı seçmenler konusunda emin değilim ... Bunu yapacak itibarım bile yok! Yorumları gönderilerle satır içine koymaktan hoşlanmamamın nedeni, tek bir gönderi için binlerce yorum aldığım (olası olmayan) senaryoyu göz önünde bulundurmaktır. Yazının içeriğine her erişmek istediğimde yorumların tamamını almak yerine, yorum koleksiyonunu sayfalandırabilmek istiyorum.
ccampo

25
Yorum göndermenin en sezgisel yolu localhost'a POST yapmak : 8080 / posts / 1 / comments . Bunu yapmanın en basit ve en anlamlı yolu değil mi? Ve aynı zamanda, özel bir yorum havuzuna sahip olmanız gerekir. Buna izin vermeyen yay mı yoksa HAL standardı mı?
aycanadal

4
@OliverGierke Bunu yapmanın hala önerilen / tek yolu bu mu? Ya çocuk null yapılamaz ( @JoinColumn(nullable=false)) değilse ? Önce çocuğu POST, ardından ana ilişkilendirmeyi PUT / PATCH yapmak mümkün olmayacaktır.
JW Lim

2
Yay veri durağıyla oluşturulmuş API'yi kullanmak için herhangi bir kılavuz var mı? 2 saat boyunca Google'da araştırdım ve hiçbir şey bulamadım. Teşekkür ederim!
Skeeve

2

2 tür Haritalama Derneği ve Kompozisyon vardır. İlişkilendirme durumunda aşağıdaki gibi birleştirme tablosu konseptini kullandık

Çalışan - 1'den n'ye> Departman

Böylece Çalışan Dernek, Departman, Çalışan_Bölüm olması durumunda 3 tablo oluşturulacak

Yalnızca kendi kodunuzda EmployeeRepository oluşturmanız gerekir. Bunun dışında haritalama şöyle olmalı:

class EmployeeEntity{

@OnetoMany(CascadeType.ALL)
   private List<Department> depts {

   }

}

Depatment Entity, forign key için herhangi bir eşleştirme içermeyecektir ... bu yüzden şimdi, tek json isteğinde Departmanlı Çalışan eklemek için POST isteğini deneyeceğiniz zaman, eklenecektir ....


1

Aynı senaryoyla karşılaştım ve bir ila birçok eşleme kullandığım ve ana varlığın kendisinden veri çektiğim için alt varlık için depo sınıfını kaldırmak zorunda kaldım. Şimdi tüm yanıtı verilerle alıyorum.



0

OneToMany eşleme için, Eşlemek istediğiniz sınıf için bir POJO ve ona @OneToMany ek açıklaması yapın ve dahili olarak bu Tablo kimliğiyle eşleştirecektir.

Ayrıca, Verileri aldığınız sınıfa Serializable arabirimini uygulamanız gerekir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.