2011-04-21 4 views
1
내가의 인스턴스에

사용자 정의 도저 매핑

class Source { 
    private List<Foo> foos = new ArrayList<Foo>(); 

    public List<Foo> getFoos() { 
    return foos; 
    } 

    public void setFoos(List<Foo> foos) { 
    this.foos = foos; 
    } 
} 

의 인스턴스를 변환 도저를 사용하려고 해요

:

자바 코드에서
class Target { 
    private List<Foo> foos = new ArrayList<Foo>(); 

    public List<Foo> getFoos() { 
    return foos; 
    } 
} 

나는이

처럼 converstion를 미리 형성 할
Source s = new Source(); 
Target t = new Target(); 
t.getFoos().addAll(s.getFoos()); 

Target에는 foos prope이 없기 때문에 Dozer는 기본적으로이 변환을 수행하지 않습니다. rty (그냥 getter).

실제로지도에 필요한 속성이 많습니다. 하나의 옵션은 map the private fields directly에 도저를 알리는 것입니다,하지만이 때문에 완전히 만족하지 않습니다 :

    나는 각 필드를 지정해야합니다
  • 는 도저 XML의 설정에 이름이 방법으로 매핑 할
  • 개인 필드를 액세스하는 것은 불량

더 좋은 방법이 있습니까?

+0

당신은't.getFoos(). addAll (s.getFoos());'가 위의'Target' 구현을위한 NPE가 될 것이라는 사실을 알고 있습니다? – Thomas

+0

죄송합니다. 제 코드를 "예식 화"하는 데 실수를했습니다. 지금 수정했습니다. –

답변

1

is-accessible 플래그 외의 다른 문제를 쉽게 해결할 수있는 방법은 없습니다.

t.getFoos().addAll(s.getFoos()); 

이 손으로 매우 무거운 작업을 많이합니다 : 하지만 당신은 수행 할 게터를 사용하는 사용자 지정 변환을 정의 할 수 있습니다.

public class TestCustomConverter implements CustomConverter { 

    public Object convert(Object destination, Object source, Class destClass, Class sourceClass) { 
    if (source == null) { 
     return null; 
    } 
    if (source instanceof Source) { 
     Target dest = null; 
     // check to see if the object already exists 
     if (destination == null) { 
     dest = new Target(); 
     } else { 
     dest = (Target) destination; 
     } 
     dest.getFoos().addAll(((Source)source).getFoos()); 
     return dest; 
    } else if (source instanceof Target) { 
     Source dest = null; 
     // check to see if the object already exists 
     if (destination == null) { 
     dest = new Source(); 
     } else { 
     dest = (Source) destination; 
     } 
     dest.setFoos(((Target)source).getFoos()); 
     return dest; 
    } else { 
     throw new MappingException("Converter TestCustomConverter used incorrectly. Arguments passed in were:" 
      + destination + " and " + source); 
    } 
    } 

내가 생각, 행운을 빌어 요 당신은 목표하는 방법을 추가 할 수

+0

NPE가 수정되었으므로이를 해결하기 위해 사용자 지정 변환기를 어떻게 사용할 수 있습니까? –

+0

당신의 도움에 감사드립니다. 그러나 위의 해결책은'Source.foos'를'Target.foos'에 매핑하기 위해서만 작용할 것입니다. 대상 클래스에 getter 만있는 두 ListType 속성을 매핑하는 데 사용할 솔루션이 필요합니다. –

+0

@don 이것은 사실이지만 getter를 사용하기 위해 부모 클래스에 대한 지식이 필요하므로 일반적으로 목록을 매핑 할 수 없습니다. 이것이 내가 생각할 수있는 유일한 해결책이다. – Tnem

1

: 대신 세터의 게터를 사용 SourceTarget 사이 (http://dozer.sourceforge.net/documentation/customconverter.html 참조) 사용자 정의 변환을 정의해야합니다 :

public void addFoo(Foo item) { 
    foos.add(item); 
} 

<mapping> 
    <class-a>Source</class-a> 
    <class-b>Target</class-b> 
    <field> 
    <a>foos</a> 
    <b set-method="addFoo" type="iterate">foos</b> 
    </field> 
</mapping> 

아마 세터 또는 게터 식 EL의 사용을 허용하는 기능을 제안

1

Dozer의 대안으로 ModelMapper을 확인해보십시오. 이 시나리오를 처리하는 것은 간단하다 :

ModelMapper modelMapper = new ModelMapper(); 
modelMapper.getConfiguration() 
    .enableFieldMatching(true) 
    .setFieldAccessLevel(AccessLevel.PRIVATE); 

모든 개인 필드이 가능 필드 일치.

Target target = modelMapper.map(source, Target.class); 

체크 아웃 추가 정보를위한 ModelMapper 사이트 : 매핑 수행하려면 예를 들어 당신이 목록 값에 대한 세터가없는 경우

http://modelmapper.org

0

(나는 어떤 이유 있었다 같은 ...) "와 결합하여 필드 매핑을 사용하여"키 "를 사용할 수있는 속성을 식별 할 수 있습니다.

<field custom-converter="de.xyz.custom.MyConverter"> 
    <a key="variablename">this</a> 
    <b>targetvariablename</b> 
</field> 

변환기."variablename"필드를 포함하는 Object가 소스로 제공됩니다. 이제는 필요한 방식으로 소스 객체를 조작 할 수 있습니다.이 경우 getter를 사용하고 목록을 가져오고 addAll()을 사용하면 좋습니다.

관련 문제