Интеграция ModelMapper с Jooq Record
===== POJO =====
// Employee POJO
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class)
public class Employee implements Serializable {
private Integer id;
private String name;
private Integer companyId;
// assume getters ,setters and serializable implementations.
}
// Company POJO
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class)
public class Company implements Serializable {
private Integer id;
private String name;
// assume getters ,setters and serializable implementations.
}
// EmployeeVO POJO
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class)
public class EmployeeVO implements Serializable {
private Employee employee;
private Company company;
// assume getters ,setters and serializable implementations.
}
===== Мой класс слоя DAO =====
public List<EmployeeVO> getEmployees(){
// configuring model mapper.
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration()
.addValueReader(new RecordValueReader())
.setSourceNameTokenizer(NameTokenizers.UNDERSCORE);
//property map configuration.
PropertyMap<Record, EmployeeVO> employeeVOMap = new PropertyMap<Record, EmployeeVO>() {
protected void configure() {
map().getEmployee().setName(this.<String>source("name"));
map().getEmployee()..setId(this.<Integer>source("id"));
map().getCompany().setName(this.<String>source("comp_name"));
map().getCompany().setId(this.<String>source("comp_id"));
}
};
// TypeMap config
modelMapper.createTypeMap(Record.class, EmployeeVO.class);
// adding employeeVOMap .
modelMapper.addMappings(employeeVOMap);
// JOOQ query
List<Field<?>> fields = Lists.newArrayList();
// fields includes, id, name, comp_name, comp_id
SelectJoinStep query = select(dslContext, fields).from(EMPLOYEE)
.join(COMPANY)
.on(COMPANY.ID.equal(EMPLOYEE.COMPANY_ID));
Result<Record> records = query.fetch();
Record record = null;
Iterator<Record> it = records.iterator();
List<EmployeeVO> employeeList= Lists.newArrayList();
while (it.hasNext()) {
record = it.next();
EmployeeVO employeeVOObj =
modelMapper.map(record, EmployeeVO.class);
employeeList.add(employeeVOObj);
}
return employeeList;
}
===== Журнал ошибок =====
1) Ошибка mapping org.jooq.impl.RecordImpl to com.myportal.bingo.db.model.EmployeeVO
1 ошибка] с первопричиной java.lang.ArrayIndexOutOfBoundsException: -1
Примечание: ModelMapper выдает вышеупомянутое исключение, когда оно достигает метода ниже.
private void matchSource(TypeInfo<?> sourceTypeInfo, Mutator destinationMutator)
в ImplicitMappingBuilder.java
sourceTypeInfo.getAccessors() is null.
Любая помощь?
1 ответ
Была та же проблема, или, по крайней мере, которая выглядела одинаково. (Вы можете перейти непосредственно к моему решению в последнем абзаце.) Много отладки показали следующее:
если средства доступа в этой строке (упомянутые в вашем вопросе) являются нулевыми, то accessors = PropertyInfoSetResolver.resolveAccessors(source, type, configuration)
строка в классе TypeInfoImpl выполняется, и причиной исключения в моем случае был этот вызов:
valueReader.get(source, memberName)
в следующем фрагменте кода в методе 'resolAccessors' в классе PropertyInfoSetResolver:
if (valueReader == null)
resolveProperties(type, true, configuration, accessors);
else {
NameTransformer nameTransformer = configuration.getSourceNameTransformer();
for (String memberName : valueReader.memberNames(source))
accessors.put(nameTransformer.transform(memberName, NameableType.GENERIC),
new ValueReaderPropertyInfo(valueReader, valueReader.get(source, memberName),
memberName));
который заканчивается в source.getValue(memberName.toUpperCase())
, где source
это запись JOOQ; InvoiceRecord в моем случае. И - тада - по какой-то причине invoice.getValue("INVOICE_ID")
заканчивается в исключении (нет такого поля и, следовательно, indexOf
возвращается -1
который вызывает ArrayIndexOutOfBoundsException), в то время как invoice.getValue("invoice_id")
совершенно нормально.
Так else
условие (тот же кусок кода выше) не был правильным способом выполнения кода, и if
дело оказалось в порядке.
Вот что мне помогло в моем конкретном случае: удаление строки modelMapper.getConfiguration().addValueReader(new RecordValueReader())
, Надеюсь, это вам тоже поможет.