2017-02-19 8 views
2

Возможно ли определить различные проекции по субтипам и данным Spring REST использовать наиболее конкретную проекцию типа класса?Использование различных прогнозов для каждого подтипа объекта

Этот вопрос был выставлен по вопросу JIRA DATAREST-739, а также существует комманда слияния, но это не отображается на официальном changelog, а также я не нашел никакой документации или руководства по ее решению с текущими выпусками.

Прецедент образец используется в вопросе:

@Entity 
@Inheritance(strategy=InheritanceType.JOINED) 
@DiscriminatorColumn(name="type") 
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type") 
public abstract class Message implements Identifiable<UUID> { ... } 

@Entity 
@DiscriminatorValue("TEXT") 
@JsonTypeName("TEXT") 
public class TextMessage extends Message { ... } 

@Entity 
@DiscriminatorValue("TODO") 
@JsonTypeName("TODO") 
public class TodoMessage extends Message { Boolean isDone; } 

@Projection(name = "summary", types = TodoMessage.class) 
public class TodoMessageSummary { Boolean getIsDone(); } 

@Projection(name = "summary", types = TextMessage.class) 
public class TextMessageSummary { ... } 

public interface MessageRepo extends JpaRepository<Message, UUID> { ... } 

@RepositoryRestResource(excerptProjection = TodoMessageSummary.class) 
public interface TodoMessageRepo extends JpaRepository<Message, UUID> { ... } 

@RepositoryRestResource(excerptProjection = TextMessageSummary.class) 
public interface TextMessageRepo extends JpaRepository<TextMessage, UUID> { ... } 

Первый вопрос: как определить проекцию отрывок для MessageRepo использовать TodoMessageSummary для TodoMessage лиц и TextMessageSummary для Отпрака?

Вторая проблема: как определить проекцию для другого объекта с полем сообщения? Скажем, у вас есть следующие:

@Projection(name = "summary", types = Dashboard.class) 
public class DashboardSummary { 
    List<Message> getMessages(); 
} 

РЕШИТЬ:

ответ

1

Хитрости является использование наследования в подтипе проекции:

@Projection(name = "summary", types = Message.class) 
public class MessageSummary { 
    @Value("#{target.getClass().getSimpleName()}") 
    String getType();  
} 

@Projection(name = "summary", types = TextMessage.class) 
public class TextMessageSummary extends MessageSummary { ... } 

@Projection(name = "summary", types = TodoMessage.class) 
public class TodoMessageSummary extends MessageSummary { 
    Boolean getIsDone(); 
} 

The Spring REST @RepositoryRestResource возвращает массив сообщений, используя конкретную проекцию подтипа (IsDone должен появиться в случаях TodoMessage)

Этот вопрос немного сложнее, если вам нужно сделал то же самое в extendend @RequestMapping в Controller, чтобы сделать это я использую следующий snnipeed:

Page<Message> results = repository.findAll(predicate, pageable); 
    Converter<? super Message, ? extends MessageSummary> converter= l -> { 
     if(l instanceof TextMessage){ 
      return projectionFactory.createProjection(TextMessageSummary.class,l); 
     } 
     else if(l instanceof TodoMessage){ 
      return projectionFactory.createProjection(TodoMessageSummary.class,l); 
     } 
     else { 
      return projectionFactory.createProjection(MessageSummary.class,l); 
     } 
    }; 
    Page<MessageSummary> projected =results.map(converter); 
    return pagedAssembler.toResource(projected); 

Обратите внимание, что если требуется только ресурс информации типа на интерфейсе только для чтения цели (т.е. для POST/PUT использовать конкретные конечные точки подтипов) Я думаю, что это на самом деле не нуждающееся использование в @JsonTypeInfo потому что с помощью SPEL в проекции позволяет получить этот вид информацию более простой и гибкой:

@Value("#{target.getClass().getSimpleName()}") 
String getType(); 
1

Да, это возможно. У нас есть такая структура подтипов в нашем приложении.

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, 
     include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true) 
public abstract class Vehicle { 
    protected VehicleType type; 
} 

public class Plane extends Vehicle { 
    private String title; 
} 

Проекция для них:

public interface VehicleProjection { 
    String getType(); 
} 

@Projection(name = "default", types = Plane.class) 
public interface PlaneProjection extends VehicleProjection { 
    String getTitle(); 
} 

И репозитории отдыха:

@RepositoryRestResource(collectionResourceRel = "collectionName", path = "path", 
     excerptProjection = VehicleProjection.class) 
public interface RestVehicleRepository<T extends Vehicle> extends MongoRepository<T, String> { 

} 

Также мы зарегистрировали эти проекции в конфигурации. Не уверен, будет ли это требуется для вашего дела, потому что у нас есть более одной проекции для каждого подтипа:

@Configuration 
public class CustomRestConfigurerAdapter extends RepositoryRestConfigurerAdapter { 
@Override 
     public void configureRepositoryRestConfiguration(final RepositoryRestConfiguration config) { 
      config.getProjectionConfiguration().addProjection(PlaneProjection.class, 
        "default", Plane.class); 
    } 
} 
+0

Спасибо за ваш ответ, мои проблемы было то, что мне нужны прогнозы подтипов на пользовательском сопоставлении контроллера. Я, наконец, решил это и во время процесса. Позвольте мне получить знания по другим полезным вопросам – pdorgambide

Смежные вопросы