![](/img/trans.png)
[英]DTO mapping and updating to a Database with Java, Dozer and Hibernate
[英]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.