1

我有实体UserEvent它们之间有many to many关系。如果我尝试将用户对象从 Controller 返回到 REST API,则会导致循环依赖。

我决定使用DTOs我将使用的地方,而不是List<Event>仅仅List<Integer>代表事件对象的 id。

但是,如果我尝试创建 custom 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);
}

最后,我的PropertyMap

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);
    }

}

如果我尝试使用 rest 获取,这是一个例外:

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)
4

1 回答 1

1

我有同样的问题,我通过将 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());
}

}

于 2017-04-13T07:20:05.710 回答