- 实体
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/