我正在尝试使用Dozer来转换
的实例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;
}
}
在Java代码中,我会像这样预先形成转换
Source s = new Source();
Target t = new Target();
t.getFoos().addAll(s.getFoos());
默认情况下,Dozer不会执行此转换,因为Target
没有foos
属性(只是一个getter)。
实际上,我有很多这样的属性需要映射。一种选择是告诉Dozer map the private fields directly,但这并不完全令人满意,因为:
有更好的方法吗?
答案 0 :(得分:1)
除is-accessible
标志外,没有其他方法可以解决这个问题。
但您可以定义一个使用getter执行的自定义转换器:
t.getFoos().addAll(s.getFoos());
这将是非常沉重的工作和很多工作。您需要在使用getter而不是setter的Source
和Target
之间定义自定义转换器(请参阅http://dozer.sourceforge.net/documentation/customconverter.html):
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);
}
}
我认为,祝你好运
答案 1 :(得分:1)
您可以向Target添加方法:
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>
可能建议允许在setter或getter表达式中使用EL的功能
答案 2 :(得分:1)
您可以查看ModelMapper作为Dozer的替代方案。处理这种情况是微不足道的:
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration()
.enableFieldMatching(true)
.setFieldAccessLevel(AccessLevel.PRIVATE);
这为所有私有字段启用了字段匹配。要执行映射:
Target target = modelMapper.map(source, Target.class);
查看ModelMapper网站了解更多信息:
答案 3 :(得分:0)
例如,如果您没有列表值的setter(就像我出于某种原因......),您可以将字段映射与“this”结合使用,以识别您可以使用“key”的属性:
<field custom-converter="de.xyz.custom.MyConverter">
<a key="variablename">this</a>
<b>targetvariablename</b>
</field>
然后,您可以继续实施转换器。您将获得包含字段“variablename”作为源的Object。你现在能够以你需要的方式操作源对象(在这种情况下使用getter,获取列表,addAll()并且你很好)。