Интеграция 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()), Надеюсь, это вам тоже поможет.

Другие вопросы по тегам