春季多对多关联DTO转换

huangapple 未分类评论44阅读模式
英文:

Spring Many to Many Association DTO Conversion

问题

我在Spring中使用Hibernate进行持久化有一个标准的多对多关系为了简洁起见构造函数和setter方法被省略

@Entity
@Table(name = "a")
public class A {
   
   @ManyToMany(mappedBy = "as")
   private Set<B> bs;
}

@Entity
@Table(name = "bs")
public class B {
   
   @ManyToMany
   @JoinTable(
           name = "b_a",
           joinColumns = @JoinColumn(name = "b_id", referencedColumnName = "id"),
           inverseJoinColumns = @JoinColumn(name = "a_id", referencedColumnName = "id")
   )
   private Set<A> as = new HashSet<>();
}

我还为每个类创建了DTO并且我有用于在它们之间进行转换的静态方法由于多对多关系我需要实现一种状态跟踪器以防止程序陷入无限递归

public final class DTOEntityMapper {

    private static class StateHolder {
        private List<Object> alreadySeenObjects = new ArrayList<>();

        void addObject(Object o){
            alreadySeenObjects.add(o);
        }

        boolean contains(Object o){
            return alreadySeenObjects.contains(o);
        }
    }

    public static BDTO fromBToDTO(B b) {
        return fromBToDTO(b, new StateHolder());
    }

    private static BDTO fromBToDTO(B b, StateHolder state) {
       state.addObject(b);
       return BDTO.builder()
            .withAs(b.getAs().stream().filter(item -> !state.contains(item)).map(e -> fromAToDTO(e, state)).collect(Collectors.toSet()))
            .build();
    }
}

// 注意:fromAToDTO执行相同的操作。

然而当我尝试测试时出现了断言失败

@Test
public void convertFromBToBDTO() {

    A a = new A("a");
    B b = new B("b");

    b.setAs(ImmutableSet.of(a));
    a.setBs(ImmutableSet.of(b));

    ADTO aDTO = new ADTO("a");
    BDTO bDTO = new BDTO("b");

    bDTO.setAs(ImmutableSet.of(aDTO));
    aDTO.setBs(ImmutableSet.of(bDTO));

    BDTO expected = bDTO;

    assertThat(DTOEntityMapper.fromBToDTO(b)).isEqualTo(expected);
}

实际结果BDTO{as=[ADTO{bs=}]}

预期结果BDTO{as=[ADTO{bs=b1}]}

基本上我对在数据模型和DTO之间进行转换时如何处理多对多关系感到困惑希望这能够理解
英文:

I have a standard many to many relationship in Spring with persistence using Hibernate. Constructors and setters left out for brevity.

@Entity
@Table(name = &quot;a&quot;)
public class A {

   @ManyToMany(mappedBy = &quot;as&quot;)
   private Set&lt;B&gt; bs;
}

@Entity
@Table(name = &quot;bs&quot;)
public class B {

   @ManyToMany
   @JoinTable(
           name = &quot;b_a&quot;,
           joinColumns = @JoinColumn(name = &quot;b_id&quot;, referencedColumnName = &quot;id&quot;),
           inverseJoinColumns = @JoinColumn(name = &quot;a_id&quot;, referencedColumnName = &quot;id&quot;)
   )
   private Set&lt;A&gt; as = new HashSet&lt;&gt;();
}

I also have DTOs for each of these classes and I have static methods to transfer between them. Due to the many-to-many relationship, I need to implement a form of state tracker to stop the program getting caught in infinite recursion.

public final class DTOEntityMapper {

    private static class StateHolder {
        private List&lt;Object&gt; alreadySeenObjects = new ArrayList&lt;&gt;();

        void addObject(Object o){
            alreadySeenObjects.add(o);
        }

        boolean contains(Object o){
            return alreadySeenObjects.contains(o);
        }
    }

    public static BDTO fromBToDTO(B b) {
        return fromBToDTO(b, new StateHolder());
    }

    private static BDTO fromBToDTO(B b, StateHolder state) {
       state.addObject(b);
       return BDTO.builder()
            .withAs(b.getAs().stream().filter(item -&gt; !state.contains(item)).map(e -&gt; fromAToDTO(e, state)).collect(Collectors.toSet()))
            .build();
    }
}

    // Note: fromAToDTO does same thing.

However when I try and test I get an assertion failure:

   @Test
   public void convertFromBToBDTO() {

    A a = new A(&quot;a&quot;);
    B b = new B(&quot;b&quot;);

    b.setAs(ImmutableSet.of(a));
    a.setBs(ImmutableSet.of(b));

    aDTO ADTO = new ADTO(&quot;a&quot;);
    bDTO BDTO = new BDTO(&quot;b&quot;);

    bDTO.setAs(ImmutableSet.of(aDTO));
    aDTO.setBs(ImmutableSet.of(bDTO));

    BDTO expected = bDTO;

    assertThat(DTOEntityMapper.fromBToDTO(b)).isEqualTo(expected);
}

Actual: BDTO{as=[ADTO{bs=}]}
Expected: BDTO{as=[ADTO{bs=b1}]}

Basically I am confused with how I deal with many-to-many relationships when converting between the data model and DTOs. Hopefully this makes sense!

huangapple
  • 本文由 发表于 2020年4月9日 19:11:40
  • 转载请务必保留本文链接:https://java.coder-hub.com/61119819.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定