2015-02-10 6 views
6

Ich möchte nicht meine Modellklassen (jpa-Entities), sondern eine andere Teilmenge ihrer Attribute mit verschiedenen Datentransportobjekten (DTOs) verfügbar machen. Die Idee ist DTO CrudRepository <-> JpaRepository <-> entities, und ich möchte über Spring Data REST die DTO CrudRepository freilegen.Wie kann ein benutzerdefiniertes DTO-Crud-Repository mit Spring-Daten-REST verfügbar gemacht werden?

Beispiel:

Entity:

@Entity 
@Table(name = "groups") 
public class Group { 

    private Long id; 
    private String name; 
    private Set<User> users; 
    // other attributes 

    @Id 
    @GeneratedValue 
    @Column(name = "group_id") 
    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    @Column(name = "name", nullable = false) 
    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    @OneToMany(mappedBy = "group") 
    public Set<User> getUsers() { 
     return users; 
    } 

    public void setUsers(Set<User> users) { 
     this.users = users; 
    } 

    // other getters and setters 

} 

JpaRepository:

@RepositoryRestResource(exported = false) 
public interface GroupDao extends JpaRepository<Group, Long> { 
} 

DTO:

public class GroupWithoutRelationsDto { 

    private Long id; 
    private String name; 

    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    @NotBlank 
    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

} 

DTO CrudRepository:

public interface GroupDtoDao extends CrudRepository<GroupWithoutRelationsDto, Long> { 
} 

Umsetzung:

@Repository 
public class GroupDtoDaoImpl extends GenericDtoDao<GroupWithoutRelationsDto, Group, Long> implements GroupDtoDao { 

    @Autowired 
    private GroupDao groupDao; 

    @Override 
    protected CrudRepository<Group, Long> getModelDao() { 
     return groupDao; 
    } 

    @Override 
    protected <S extends GroupWithoutRelationsDto> Long getDtoId(S dto) { 
     return dto.getId(); 
    } 

    @Override 
    protected Long getModelId(Group model) { 
     return model.getId(); 
    } 

    @Override 
    protected <S extends GroupWithoutRelationsDto> S modelToDto(Group model, S dto) { 
     dto.setId(model.getId()); 
     dto.setName(model.getName()); 
     return dto; 
    } 

    @Override 
    protected <S extends GroupWithoutRelationsDto> Group dtoToModel(S dto, Group model) { 
     model.setId(dto.getId()); 
     model.setName(dto.getName()); 
     return model; 
    } 

    @Override 
    protected Group newModel() { 
     return new Group(); 
    } 

    @Override 
    protected GroupWithoutRelationsDto newDto() { 
     return new GroupWithoutRelationsDto(); 
    } 

} 

GenericDtoDao:

@NoRepositoryBean 
public abstract class GenericDtoDao<D, M, ID extends Serializable> implements CrudRepository<D, ID> { 

    protected abstract CrudRepository<M, ID> getModelDao(); 

    protected abstract <S extends D> ID getDtoId(S dto); 

    protected abstract ID getModelId(M model); 

    protected abstract <S extends D> S modelToDto(M model, S dto); 

    protected abstract <S extends D> M dtoToModel(S dto, M model); 

    protected abstract M newModel(); 

    protected abstract D newDto(); 

    @Override 
    public D findOne(ID id) { 
     return modelToDto(getModelDao().findOne(id), newDto()); 
    } 

    @Override 
    public <S extends D> S save(S entity) { 
     Assert.notNull(entity, "The entity must not be null!"); 
     if (getDtoId(entity) == null) { 
      return create(entity); 
     } 
     return update(entity); 
    } 

    protected <S extends D> S create(S entity) { 
     Assert.notNull(entity, "The entity must not be null!"); 
     if (getDtoId(entity) != null) { 
      Assert.isTrue(!exists(getDtoId(entity)), "The entity ID must be null or not exist!"); 
     } 
     return modelToDto(getModelDao().save(dtoToModel(entity, newModel())), entity); 
    } 

    protected <S extends D> S update(S entity) { 
     Assert.notNull(entity, "The entity must not be null!"); 
     M model = getModelDao().findOne(getDtoId(entity)); 
     Assert.notNull(model, "The entity must exist!"); 
     return modelToDto(getModelDao().save(dtoToModel(entity, model)), entity); 
    } 

    // other CrudRepository methods 

} 

In diesem Beispiel habe ich GroupDtoDao mit Feder Daten REST verfügbar machen möchten.

In anderen Beans kann ich sowohl GroupDao als auch GroupDtoDao autowire, also werden beide von Spring's Kontext verwaltet. Wenn ich GroupDao mit @RepositoryRestResource(exported = false) nicht annotiere, wird das JpaRepository als REST-Service verfügbar gemacht, also nehme ich an, dass Spring Data REST gut konfiguriert ist.

Wie kann ich sagen, dass es mein benutzerdefiniertes CrudRepository freigibt?

+0

Haben Sie das jemals herausgefunden? Ich bin auch an der Antwort interessiert, habe aber keine saubere Lösung. Meine beste Idee war, einen benutzerdefinierten JSON ObjectMapper bereitzustellen und innerhalb des Mappers die Zuordnung zu DTO vorzunehmen und stattdessen den DTO zu schreiben. – Jay

+0

Ich habe noch keine automatische Lösung gefunden, ich habe immer noch einen benutzerdefinierten CrudRestController, der meine DtoDaos-Methoden umschließt –

Antwort

2

Dort ist a JIRA issue zu klären, wie dies zu tun ist.

Fürs Erste sagt das SDR-Team: "Wir empfehlen generell, Jackson Mixins einfach zu verwenden, um benutzerdefinierte Serializer einzubinden, die Ausgabe anzupassen usw. Siehe die Spring RESTBucks für ein Beispiel."

Verwandte Themen