簡體   English   中英

Hibernate對象的Dozer映射到DTO

[英]Dozer mapping for Hibernate object to DTO

我嘗試使用Dozer將我的域實體轉換為DTO對象。 所以,我想將PersistentList,PersistentBag,...從我的域實體轉換為ArrayList,...在我的DTO對象中,以避免延遲問題。

這是我的兩個域實體的示例:

public class User {
      private Collection<Role> roles;
      ...
}

public class Role {
      private Collection<User> users;
      ...
}

我的DTO對象是相同的,除了類是DTO類型。 因此,要將域轉換為DTO對象,我使用以下Dozer映射:

 <configuration>
  <custom-converters>
   <converter type=com.app.mapper.converter.BagConverter">
    <class-a>org.hibernate.collection.PersistentBag</class-a>
    <class-b>java.util.List</class-b>
   </converter>
  </custom-converters>
 </configuration>

 <mapping>
  <class-a>com.app.domain.User</class-a>
  <class-b>com.app.dto.UserDTO</class-b>
 </mapping>

 <mapping>
  <class-a>com.app.domain.Role</class-a>
  <class-b>com.app.dto.RoleDTO</class-b>
 </mapping>

BagConverter是一個Dozer自定義轉換器,它的代碼是:

  public class BagConverter<T> extends DozerConverter<PersistentBag, List>{

 public BagConverter() {
  super(PersistentBag.class, List.class);
 }

 public PersistentBag convertFrom(List source, PersistentBag destination) {
  PersistentBag listDest = null;

  if (source != null) {

   if (destination == null) {
    listDest = new PersistentBag();
   } else {
    listDest = destination;
   }

   listDest.addAll(source);
  }

  return listDest;
 }

 public List convertTo(PersistentBag source, List destination) {
  List listDest = null;

  if (source != null) {

   if (destination == null) {
    listDest = new ArrayList<T>();
   } else {
    listDest = destination;
   }

   if (source.wasInitialized()) {
    listDest.addAll(source);
   }
  }

  return listDest;
 }}

因此,我得到一個包含帶角色的PersistentBag的User對象。 我在該對象上應用dozer映射器映射以獲取UserDTO對象。 我得到的結果是一個UserDTO對象,其ArrayList為Role,而沒有像我所希望的RoleDTO的ArrayList。

我以為即使我使用自定義轉換器,推土機也會轉換我的列表內容。 這不是正確的方法嗎? 如果不是,如何通過將persitent集合替換為經典java集合將我的域實體轉換為dto對象?

謝謝你的幫助。

西爾萬。

不幸的是,當您注冊 CustomConverter您將負責映射對象(在您的案例中為集合),包括其所有內容,屬性,元素等。

正如我現在看到的(我之前沒有看到它,它必須是某種新功能)。 有可能使用MapperAware接口,如章節末尾所述的Dozer文檔中的自定義類型轉換器 我想這正是滿足您需求的原因。

我嘗試使用Dozer將我的域實體轉換為DTO對象。 所以,我想將PersistentList,PersistentBag,...從我的域實體轉換為ArrayList,...在我的DTO對象中,以避免延遲問題。

我得到了最后一句,但我不明白為什么你需要處理ohcPersistentBag (等等),因為這個類一個List 只需使用這樣的東西:

<mapping>
  <class-a>com.myapp.domain.User</class-a>
  <class-b>com.myapp.dto.UserDTO</class-b>
  <field>
    <a>roles</a>
    <b>roles</b>
    <a-hint>com.myapp.domain.Role</a-hint>
    <b-hint>com.myapp.dto.RoleDTO</b-hint>
  </field>
</mapping>

並在分離實體之前執行轉換(這是您的問題的關鍵)。

正如Pascal所說,我沒有直接使用PersistentBags的意義。 如果在你的@Entity POJO中你將你的角色列表聲明為經典的java.util.List那么Hibernate會自動使用它的內部表示。 這也是您在序列化過程中無法使用POJO的原因。 澄清:

@Entity
public class User {
  private java.util.List<Role> roles = new java.util.Arraylist<Role>(); //Hibernate doesn't really care about this new Arraylist stuff, it will use its org.hibernate.collection.PersistentList
  ... //other fields and methods
}

現在,當您想要將實體POJO轉換為DTO對象時,您只需使用Pascal建議的映射,即

<mapping>
  <class-a>com.myapp.domain.User</class-a>
  <class-b>com.myapp.dto.UserDTO</class-b>
  <field>
    <a>roles</a>
    <b>roles</b>
    <a-hint>com.myapp.domain.Role</a-hint>
    <b-hint>com.myapp.dto.RoleDTO</b-hint>
  </field>
</mapping>

在關閉事務之前進行轉換以避免延遲初始化異常,例如:

@Transactional
public UserDTO getUser(...) {
  User user = dao.getUser(...);
  UserDTO dto = //Place your Dozer conversion here
  return dto;
}

正如我的小記,我出於同樣的原因使用了Dozer,這就像魅力一樣。

我還測試了另一種解決方案,沒有自定義轉換器:

<mapping>
    <class-a>com.myapp.domain.User</class-a>
    <class-b>com.myapp.dto.UserDTO</class-b>
    <field>
        <a>roles</a>
        <b>roles</b>
        <a-hint>com.myapp.domain.Role</a-hint>
        <b-hint>com.myapp.dto.RoleDTO</b-hint>
    </field>
</mapping>

還有另一個問題。 當Dozer嘗試將角色從User轉換為UserDTO中RoleDTO的角色時,我從Hibernate獲得了一個懶惰的初始化異常,因為User中的角色處於EAGER模式。

所以,我不知道如何做那個映射。 我繼續尋找解決這些問題的方法

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM