2017-02-21 53 views
2

У меня проблема с Spring Data Rest, используемой с Spring Data JPA. Я использую Spring-boot 1.4.4.RELEASE.Данные о запаздывании данных и jpa @OneToMany дубликаты «_links»

Вот моя весна-данные остального хранилище:

public interface ProfileJpaRepository extends JpaRepository<Profile, Long> { 
} 

Вот мои лица (получатели и установщики не показан для краткости).

Profile.java:

@Entity 
@Table(name = "PROFILE") 
public class Profile { 

    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private Long id; 

    private String description; 

    // Don't use mappedBy="profile" because attributes are not persisted properly 
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true) 
    @JoinColumn(name = "PROFILE_ID") 
    private Set<Attribute> attributes; 

    ... 
} 

Attribute.java

@Entity 
@Table(name = "ATTRIBUTE") 
public class Attribute { 

    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    @Column(name = "ID") 
    private Long id; 

    private String uri; 

    @ManyToOne(fetch = FetchType.EAGER) 
    private Profile profile; 

    @ElementCollection(fetch = FetchType.EAGER) 
    @CollectionTable(name="ATTRIBUTE_DATAS") 
    private List<String> datas = new ArrayList<>(); 

    public Attribute() {} 

    public Attribute(String uri, List<String> datas) { 
     this.uri = uri; 
     this.datas = datas; 
    } 

    ... 
} 

POST-на "http://localhost:8880/profiles", чтобы создать объект:

{ 
    "description" : "description-value", 
    "attributes" : [ 
     { 
      "uri" : "uri-a", 
      "datas" : ["uri-a-value"] 
     }, 
     { 
      "uri" : "uri-b", 
      "datas" : ["uri-b-value"] 
     } 
    ] 
} 

И вот результат, когда я хит http://localhost:8880/profiles:

{ 
    "_embedded" : { 
    "profiles" : [ { 
     "description" : "description-value", 
     "attributes" : [ { 
     "uri" : "uri-a", 
     "datas" : [ "uri-a-value" ], 
     "_links" : { 
      "profile" : { 
      "href" : "http://localhost:8880/profiles/1" 
      } 
     } 
     }, { 
     "uri" : "uri-b", 
     "datas" : [ "uri-b-value" ], 
     "_links" : { 
      "profile" : { 
      "href" : "http://localhost:8880/profiles/1" 
      } 
     } 
     } ], 
     "_links" : { 
     "self" : { 
      "href" : "http://localhost:8880/profiles/1" 
     }, 
     "profile" : { 
      "href" : "http://localhost:8880/profiles/1" 
     } 
     } 
    } ] 
    }, 
    "_links" : { 
    "self" : { 
     "href" : "http://localhost:8880/profiles" 
    }, 
    "profile" : { 
     "href" : "http://localhost:8880/profile/profiles" 
    } 
    }, 
    "page" : { 
    "size" : 20, 
    "totalElements" : 1, 
    "totalPages" : 1, 
    "number" : 0 
    } 
} 

Я думаю, что есть проблема, потому что "_links" указаны под каждым атрибутом. Скорее всего, я бы ожидал что-то вроде этого:

{ 
    "_embedded" : { 
    "profiles" : [ { 
     "description" : "description-value", 
     "attributes" : [ { 
     "uri" : "uri-a", 
     "datas" : [ "uri-a-value" ] 
     }, { 
     "uri" : "uri-b", 
     "datas" : [ "uri-b-value" ] 
     } ], 
     "_links" : { 
     "self" : { 
      "href" : "http://localhost:8880/profiles/1" 
     }, 
     "profile" : { 
      "href" : "http://localhost:8880/profiles/1" 
     } 
     } 
    } ] 
    }, 
    "_links" : { 
    "self" : { 
     "href" : "http://localhost:8880/profiles" 
    }, 
    "profile" : { 
     "href" : "http://localhost:8880/profile/profiles" 
    } 
    }, 
    "page" : { 
    "size" : 20, 
    "totalElements" : 1, 
    "totalPages" : 1, 
    "number" : 0 
    } 
} 

Обратите внимание, что я был переход от MongoRepository к JpaRepository, и используя MongoRepository эти "_links" не были «дублируются».

Может кто-то пролить свет на это? Я что-то неправильно исказил в своих судах JPA? Нужно ли мне что-то настраивать в остальном репозитории?

Более подробную информацию о версиях зависимостей можно найти здесь если вам это нужно, я не переопределить эти (http://docs.spring.io/spring-boot/docs/1.4.4.RELEASE/reference/html/appendix-dependency-versions.html)

Спасибо.

+0

Вы знаете, как/почему _links генерируются ли ваш код? Я предполагаю, что это происходит во время JSON-Serialization, но я никогда не сталкивался с ними, используя конфигурации по умолчанию. –

+2

@TorstenN., это делается автоматически с помощью ProfileJpaRepository, Spring Data Rest видит, что он расширяет JpaRepository, и он «автоматически открывает доступный REST API для вашей модели домена, используя HAL как тип носителя». – Nis

ответ

0

Чтобы решить эту проблему, я использую проекции (более подробную информацию здесь: http://docs.spring.io/spring-data/rest/docs/current/reference/html/#projections-excerpts). Я не знал об этой функции при публикации.

Я должен был аннотирование моего репозитория и сказать ему, чтобы использовать мое InlineAttributes проекцию:

import org.springframework.data.rest.core.annotation.RepositoryRestResource; 

@RepositoryRestResource(excerptProjection = InlineAttributes.class) 
public interface ProfileJpaRepository extends JpaRepository<Profile, Long> { 
} 

В классе Attribute я должен был добавить @JsonIgnore аннотации:

import com.fasterxml.jackson.annotation.JsonIgnore; 

@Entity 
@Table(name = "ATTRIBUTE") 
public class Attribute { 
    ... 

    @ManyToOne(fetch = FetchType.EAGER) 
    @JsonIgnore 
    private Profile profile; 

    ... 
} 

и проекцию InlineAttributes класс, который я должен был создать. Я уточнил порядок, поскольку он не был таким же, как и раньше:

import org.springframework.data.rest.core.config.Projection; 
import com.fasterxml.jackson.annotation.JsonPropertyOrder;  

@Projection(name = "inlineAttributes", types = { Profile.class }) 
@JsonPropertyOrder({ "description", "attributes" }) 
public interface InlineAttributes { 

    public String getDescription(); 
    public Set<Attribute> getAttributes(); 
} 

И тогда вы должны применить проецирование, если вы звоните остальное конечную точку:

http://localhost:8880/profiles?projection=inlineAttributes