java - 何时使用 @OneToMany 和 @ManyToOne 以及 MapStruct - 我得到递归无穷大

标签 java hibernate-mapping

  • 实体
Entity
@Table(name ="posts")
public class Post {

    @Id
    @SequenceGenerator(name = "jpaSequence.Post",
            sequenceName = "SEQUENCE_POST",
            allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "jpaSequence.Post")
    private Long id;
    private String subject;

    @OneToMany(mappedBy = "post", fetch = FetchType.LAZY)
    private List<Comment> comments = new ArrayList<>();

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn
    private User user;


    public Post() {
    }
@Entity
@Table(name = "comments")
public class Comment {

    @Id
    @SequenceGenerator(name = "jpaSequence.Comment",
            sequenceName = "SEQUENCE_COMMENT",
            allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "jpaSequence.Comment")
    private Long id;

    private String reply;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn
    private Post post;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn
    private User user;


    public Comment() {
    }
@Entity
@Table(name = "users")
public class User {

    @Id
    @SequenceGenerator(name = "jpaSequence.User",
            sequenceName = "SEQUENCE_USER",
            allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "jpaSequence.User")
    private Long id;

    private String name;
    private String email;


    public User() {
    }
  • 映射器
@Mapper(componentModel = "spring" )
public interface PostMapper {

    Post postDtoToPostEntity(PostDto dto);

    PostDto postEntityToPostDto(Post entity);

    Iterable<Post> postListDtoToPostListEntity(Iterable<PostDto> list);

    Iterable<PostDto> postListEntityToPostListDto(Iterable<Post> list);
}

@Mapper(componentModel = "spring")
public interface CommentMapper {

    Comment commentDtoToCommentEntity (CommentDto dto);

    CommentDto commentEntityToCommentDto(Comment entity);

    Iterable<Comment> commentListDtoToCommentListEntity(Iterable<CommentDto> list);

    Iterable<CommentDto> commentListEntityToCommentListDto(Iterable<Comment> list);
}

-服务

@Service
public class PostReadServiceImpl implements PostReadService {

    private PostRepository repository;

    private PostTransformer transformer;

    private CommentTransformer transformerComment;

    @Autowired
    public PostReadServiceImpl(PostRepository repository, PostTransformer transformer,
                               CommentTransformer transformerComment) {
        this.repository = repository;
        this.transformer = transformer;
        this.transformerComment = transformerComment;
    }


    @Transactional
    @Override
    public PostDto getEntryById(Long id) {

        Post entity = find(id);

        return this.transformer.transformEntityToDto(entity);
    }


    private Post find(Long id){

        return this.repository.findById(id).orElseThrow(() -> new RuntimeException("Post not found!"));
    }


    @Transactional
    @Override
    public Iterable<CommentDto> getListEntriesCommentById(Long id) {

        Iterable<Comment> listComment = findListComment(id);

        Iterable<CommentDto> commentDtoList = this.transformerComment.transformListEntityToDtoList(listComment);

        return commentDtoList;
    }

    private Iterable<Comment> findListComment(Long id){

        Post post = this.repository.findById(id).orElseThrow(() -> new RuntimeException("Post not found!"));
        List<Comment> comments = post.getComments();
        return comments;
    }
}

当使用MapStruct时,我得到无限递归。 即使我没有从接收到的对象中请求相关注释实体,我仍然会在 Debug模式下看到无限嵌套,尽管我选择了

fetch = FetchType.LAZY

谁有任何想法如何解决这个问题以及为什么它会这样工作?

最佳答案

解决方案

  • 休息
@RestController
@RequestMapping("api/read")
public class PostReadRest {

    private static final String PATH_TO_READ_POST_BY_ID = "post/{id}";

    private static final String PATH_TO_READ_POST_LIST = "post/list";

    private PostReadService service;

    @Autowired
    public PostReadRest(PostReadService service) {
        this.service = service;
    }

    @GetMapping(PATH_TO_READ_POST_BY_ID)
    public PostDto getPostById(@PathVariable String id){

        Long idLong = Long.valueOf(id);

        return service.getEntryById(idLong);
    }

}

  • 服务
@Service
public class PostReadServiceImpl implements PostReadService {

    private PostRepository repository;

    private PostTransformer transformer;

    private CommentTransformer transformerComment;

    @Autowired
    public PostReadServiceImpl(PostRepository repository, PostTransformer transformer,
                               CommentTransformer transformerComment) {
        this.repository = repository;
        this.transformer = transformer;
        this.transformerComment = transformerComment;
    }


    @Transactional
    @Override
    public PostDto getEntryById(Long id) {

        Post entity = find(id);

        PostDto postDto = this.transformer.transformEntityToDto(entity);

        return postDto;
    }


    private Post find(Long id){

        return this.repository.findById(id).orElseThrow(() -> new RuntimeException("Post not found!"));
    }


}
  • 映射器
@Mapper(componentModel = "spring")
public interface PostMapper {

    Post postDtoToPostEntity(PostDto dto);

    @Mapping(target = "post.comments", ignore = true)
    CommentDto toCommentDto(Comment entity);

    PostDto postEntityToPostDto(Post entity);

    Iterable<Post> postListDtoToPostListEntity(Iterable<PostDto> list);

    Iterable<PostDto> postListEntityToPostListDto(Iterable<Post> list);
}

  • @Mapping(target = "post.comments",ignore = true)

post - 这是字段“评论”实体的名称。

评论 - 这是字段“Post”实体的名称,但是, 这里的字段是二级字段。这是必须忽略的。

  • 变压器
@Component
public class PostTransformer {

    private PostMapper mapper;

    @Autowired
    public PostTransformer(PostMapper mapper) {
        this.mapper = mapper;
    }

    public PostDto transformEntityToDto(Post entity){

        PostDto postDto = this.mapper.postEntityToPostDto(entity);

        return postDto;
    }


    public Post transformDtoToEntity(PostDto dto){

        return this.mapper.postDtoToPostEntity(dto);
    }

    public Iterable<PostDto> transformListEntityToDtoList(Iterable<Post> listEntity){

        Iterable<PostDto> postDtoList = this.mapper.postListEntityToPostListDto(listEntity);

        return postDtoList;
    }

    public Iterable<Post> transformListDtoToEntityList(Iterable<PostDto> listDto){

        return this.mapper.postListDtoToPostListEntity(listDto);
    }

}

结果

{
    "id": 1,
    "subject": "JPA Entity Graph In Action",
    "comments": [
        {
            "id": 1,
            "reply": "Nice !!",
            "post": {
                "id": 1,
                "subject": "JPA Entity Graph In Action",
                "comments": [],
                "user": {
                    "id": 1,
                    "name": "user1",
                    "email": "user1@test.com"
                }
            },
            "user": {
                "id": 2,
                "name": "user2",
                "email": "user2@test.com"
            }
        },
        {
            "id": 2,
            "reply": "Cool !!",
            "post": {
                "id": 1,
                "subject": "JPA Entity Graph In Action",
                "comments": [],
                "user": {
                    "id": 1,
                    "name": "user1",
                    "email": "user1@test.com"
                }
            },
            "user": {
                "id": 3,
                "name": "user3",
                "email": "user3@test.com"
            }
        }
    ],
    "user": {
        "id": 1,
        "name": "user1",
        "email": "user1@test.com"
    }
}

这很重要

如果您没有指向方法(它有一个注释 @Override)注释 @Transactional ,您会遇到 异常,如果您使用 - <强>FetchType.LAZY

    @Transactional
    @Override
    public PostDto getEntryById(Long id) {

        Post entity = findEntry(id);

        List<Comment> comments = entity.getComments();

        PostDto postDto = this.transformer.transformEntityToDto(entity);

        return postDto;
    }

当事务正在执行时,当Mapper正在执行时,将会执行额外的查询,从相关的表中获取嵌套条目。

关于java - 何时使用 @OneToMany 和 @ManyToOne 以及 MapStruct - 我得到递归无穷大,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60828011/

相关文章:

java - hibernate 中的一对多映射。值即将为空

java - 列类型的奇怪 Hibernate 异常

java - 未知主机异常 : name or service not known

java - Eclipse 中属性文件中的相对路径

java - 如何通过 XA 数据源调用 DBlink

hibernate : No CurrentSessionContext configured

java - hibernate @审核: NOT_AUDITED cannot be resolved to a variable

java - 使用 Hibernate 自动创建列表

java - 在 eclipse 中使用 java 以编程方式启动 appium 服务器时花费太多时间

java - 我可以用java为ubuntu编写一个拨号监听程序吗?