模型映射器 - 如何映射不兼容的类型

时间:2017-01-05 08:20:43

标签: java rest dto modelmapper

我的实体UserEvent彼此之间有many to many个关系。如果我尝试将User对象从Controller返回到REST API,则会导致循环依赖。

我决定使用DTOs我会使用List<Event>代替List<Integer>代表事件对象ID的PropertyMap

但是如果我尝试创建自定义@Entity @Table(name = "events") @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public class Event extends AbstractEntity { @ManyToMany(cascade = CascadeType.PERSIST) @JoinTable(name = "event_participants", joinColumns = @JoinColumn(name = "event_id"), inverseJoinColumns = @JoinColumn(name = "user_id")) private List<User> eventParticipants; ,它就不起作用。你推荐不同的方法,怎么做?

活动实体

@Entity
@Table(name = "users")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class User extends AbstractEntity {

@ManyToMany(mappedBy = "eventParticipants")
private List<Event> participatingEvents;

用户实体

@RestController
@RequestMapping("/users")
public class UserController extends AbstractController {

@Autowired
private UserService userService;

@Autowired
private ModelMapper modelMapper;

@RequestMapping(method = RequestMethod.GET, value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public UserDTO find(@PathVariable("id") Integer id) {
    final User user = userService.find(id);
    if (user == null) {
        //TODO throw some exception
        return null;
    }
    UserDTO userDTO = userToDTO(user);
    return userDTO;
}

private UserDTO userToDTO(User user) {
    modelMapper.addMappings(new UserMap());
    return modelMapper.map(user, UserDTO.class);
}

UserController中

public class UserMap extends PropertyMap<User, UserDTO> {

    @Override
    protected void configure() {
        map().setFirstName(source.getFirstName());

        map().setLastName(source.getLastName());

        map().setEmail(source.getEmail());

        List<Integer> friendsDTO = new ArrayList<>();
        for(User u : source.getFriends()){
            friendsDTO.add(u.getId());
        }
        map().setFriends(friendsDTO);

        List<Integer> participatingEventsDTO = new ArrayList<>();
        for(Event e : source.getParticipatingEvents()){
            participatingEventsDTO.add(e.getId());
        }
        map().setParticipatingEvents(participatingEventsDTO);

        List<Integer> ownedEventsDTO = new ArrayList<>();
        for(Event e : source.getOwnedEvents()){
            ownedEventsDTO.add(e.getId());
        }
        map().setOwnedEvents(ownedEventsDTO);

        List<Integer> commentsDTO = new ArrayList<>();
        for(Comment c : source.getComments()){
            commentsDTO.add(c.getId());
        }
        map().setComments(commentsDTO);

        List<Integer> thingsDTO = new ArrayList<>();
        for(ThingToTake t : source.getThingsToTakeList()){
            thingsDTO.add(t.getId());
        }
        map().setThingsToTakeList(thingsDTO);
    }

}

最后,我的 PropertyMap

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.modelmapper.ConfigurationException: ModelMapper configuration errors:

1) Invalid source method java.util.List.add(). Ensure that method has zero parameters and does not return void.

2) Invalid source method java.util.List.add(). Ensure that method has zero parameters and does not return void.

3) Invalid source method java.util.List.add(). Ensure that method has zero parameters and does not return void.

4) Invalid source method java.util.List.add(). Ensure that method has zero parameters and does not return void.

5) Invalid source method java.util.List.add(). Ensure that method has zero parameters and does not return void.

5 errors
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

root cause

org.modelmapper.ConfigurationException: ModelMapper configuration errors:

1) Invalid source method java.util.List.add(). Ensure that method has zero parameters and does not return void.

2) Invalid source method java.util.List.add(). Ensure that method has zero parameters and does not return void.

3) Invalid source method java.util.List.add(). Ensure that method has zero parameters and does not return void.

4) Invalid source method java.util.List.add(). Ensure that method has zero parameters and does not return void.

5) Invalid source method java.util.List.add(). Ensure that method has zero parameters and does not return void.

5 errors
    org.modelmapper.internal.Errors.throwConfigurationExceptionIfErrorsExist(Errors.java:241)
    org.modelmapper.internal.ExplicitMappingBuilder.visitPropertyMap(ExplicitMappingBuilder.java:229)
    org.modelmapper.PropertyMap.configure(PropertyMap.java:380)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:483)
    org.modelmapper.internal.ExplicitMappingBuilder.build(ExplicitMappingBuilder.java:195)
    org.modelmapper.internal.TypeMapImpl.addMappings(TypeMapImpl.java:72)
    org.modelmapper.internal.TypeMapStore.getOrCreate(TypeMapStore.java:101)
    org.modelmapper.ModelMapper.addMappings(ModelMapper.java:93)
    com.ear.tripplan.rest.UserController.userToDTO(UserController.java:50)
    com.ear.tripplan.rest.UserController.find(UserController.java:39)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:483)
    org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

这是一个异常,如果我尝试使用rest来获取

grammar org.xtext.example.mydemo.MyDemo with org.eclipse.xtext.common.Terminals

generate myDemo "http://www.xtext.org/example/mydemo/MyDemo"

Model:
   (elements+=DocComments)*
;

DocComments hidden(WS, OTHER):
   start=StartComment name=VarComment? property=PropertyComment* end=EndComment
;

StartComment: '/**';
EndComment:'*/';
VarComment: key='@var' name=ID;
PropertyComment: key='@property' name=ID;

terminal OTHER: '*';

1 个答案:

答案 0 :(得分:0)

我遇到了同样的问题 我通过将id包装在另一个对象中来实现它

public class UserDTO {

     List<EventDTO> participatingEvents
     /// getter setter
}

public class EventDTO {
    private Long id;
    // getter setter
}

你不需要任何propertyMap或转换器

UserDTO userDTO = modelmapper.map(user, UserDTO.class);

希望有所帮助

<强>已更新

您也可以使用转换器

public class UserMap extends PropertyMap<User, UserDTO> {

@Override
protected void configure() {
    Converter<List<User>, List<Long>> converter = new AbstractConverter<List<User>, List<Long>>() {
        List<Long> result = new ArrayList<>();
        @Override
        protected List<Long> convert(List<User> source) {
            source.forEach(user -> result.add(user.getId()));
            return result;
        }
    };
    using(converter).map(source.getUsers(), destination.getUsers());
}

}