jpa 如何将实体转换为数据,反之亦然?

balp4ylt  于 2022-11-14  发布在  其他
关注(0)|答案(3)|浏览(118)

好的,我有3个实体:主题、用户、类别、图片。用户有图片,主题有用户和类别。

class Topic {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Integer id;

    @Column(nullable = false)
    String header;

    @Column(nullable = false)
    String description;

    @Column(name = "is_anonymous", nullable = false)
    boolean isAnonymous;

    @DateTimeFormat(pattern = "yyyy-MM-dd hh:mm:ss")
    @Column(name = "creation_date", nullable = false)
    LocalDateTime creationDate;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "author_id", nullable = false)
    User author;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "category_id", nullable = false)
    Category category;
}

我还有一个主题DTO

class TopicDTO {

    String header;

    String description;

    boolean isAnonymous;

    LocalDateTime creationDate;

    UserDTO userDTO;

    CategoryDTO categoryDTO;
}

我可以将ModelMapper注入到TopicService中,并用它来转换,但是它并不能像我需要的那样工作,在这种情况下,如果我试图将Topic转换为TopicDTO,在转换后的TopicDTO对象中,UserDTO和CategoryDTO将为null,但是在调试中,在转换之前,在Topic对象- Category对象和User对象都不为null时,它们被初始化了。
我尝试为每个实体编写一个CRUD服务,在其中注入扩展CrudRepository的存储库。当我从控制器TopicDTO获取时,我调用topicService.save(topicDTO),但在主题服务中,方法保存,我不想级联save user,我不想级联save categories,我想用现有的samples category和user保存主题,我怎么能做到呢?对不起我糟糕的英语

atmip9wb

atmip9wb1#

您可以使用MapStruct之类的代码生成器,我真的不太熟悉它,因为您必须学习如何注解您的DTO以便Map它们,而且它已经被弃用了。(例如,它只能用junit4测试)。
你应该使用Lombok构建器从你的实体示例化DTO。此外,你可以在TDD中使用junit5轻松地测试它,如下所示:

class TopicMapperTest {

    TopicMapper topicMapper;

    @Mock
    UserMapper userMapper;

    Clock clock;

    @BeforeEach
    void setUp() {
        topicMapper = new TopicMapper();
        clock = Clock.fixed(LocalDateTime.now().toInstant());
    }

    @Test
    void should_map_topic_to_topicDTO() {
        // Given
        Topic topic = new Topic(1, "header", "description", false, LocalDateTime.now(clock), new User(), new Category());

        TopicDTO expected = TopicDTO.builder()
                .header("header")
                .description("description")
                .isAnonymous(false)
                .creationDate(LocalDateTime.of())
                .userDTO(userMapper.mapUser(new User()))
                .categoryDTO(categoryMapper.mapCategory(new Category()))
                .build();

        // When
        TopicDTO result = topicMapper.mapTopic(topic);

        // Then
        assertEquals(expected, result);
    }
}

您的Map器应该如下所示(我让您完成它以使您的测试通过):

public class TopicMapper {

    UserMapper userMapper = new UserMapper();

    public TopicDTO mapTopic(Topic topic) {
        return TopicDTO.builder()
                .header(topic.getHeader())
                .description(topic.getDescription())
                .userDTO(userMapper.mapUser(topic.getAuthor()))
                .isAnonymous(topic.isAnonymous())
                .build();
    }
}
9q78igpj

9q78igpj2#

您可以在TopicDTO类中创建一个of方法来构造对象。提供userDTO和categoryDTO作为参数将允许将它们设置为null或它们各自的对象(如果存在)。

class TopicDTO {

    String header;

    String description;

    //all the other variables...

    public static TopicDTO of(Topic topic, UserDTO userDTO, CategoryDTO categoryDTO) {
    return new TopicDTO(
            topic.getHeader(),
            topic.getDescription(),
            topic.getIsAnonymous(),
            topic.getCreationDate(),
            userDTO,
            categoryDTO);
    }
}
ne5o7dgx

ne5o7dgx3#

你应该只使用构造函数来创建对象!在示例化对象时不要使用getter/setter,因为这是一个反模式。很难维护你已经使用过的setter和没有使用的setter。对象应该通过构造函数和关键字“new”完全创建,它将立即有一个状态。
要将EntityMap到dto,我建议创建一个简单的Mapper类,它在构造函数中接受Entity并返回新的dto对象,就这样。

相关问题