2016-12-29 2 views
0

У меня 2 объектов CallRecords и CallRecordOperators с один-ко-многим, как указано нижеMapstruct - Отправить вложенную объект, имеющий (один-ко-многим) в ответ

public class CallRecords { 

    @Id 
    @Column(name = "id", unique = true) 
    private String id; 

    @Column(columnDefinition = "varchar(255) default ''") 
    private String callerNumber = ""; 

    @OneToMany(mappedBy="callrecord") 
    private List<CallRecordOperators> callRecordOperators = new ArrayList<CallRecordOperators>(); 


    //getter setters 
} 

public class CallRecordOperators { 

    @Id 
    @Column(name = "id", length = 50, unique = true, nullable = false, insertable = false, updatable = false) 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    @JsonIgnore 
    @ManyToOne 
    @JoinColumn(name = "callRecordId") 
    private CallRecords callrecord; 

    @ManyToOne 
    @JoinColumn(name = "operatorId") 
    private Operator operator; 

    @Formats.DateTime(pattern = "yyyy-MM-dd HH:mm:yy") 
    @Column(columnDefinition = "TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP") 
    private Date startTime = new Date(); 

    @Column(columnDefinition = "varchar(100) default ''") 
    private String dialStatus; 

    //getter setter 
} 

Итак, если пользователь запрашивает все данные «CallRecords», я также должен предоставить «CallRecordOperators», поскольку они связаны.

Текущий код Mapper и DTOS

@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE) 
public interface CallRecordsMapper { 

    CallRecordsMapper INSTANCE = Mappers.getMapper(CallRecordsMapper.class); 

    @Mapping(source="callRecordOperators",target = "operators") 
    CallRecordsDto callRecordsToCallRecordsDto(CallRecords callRecords); 

    public abstract CallRecordOperatorsDto toTarget(CallRecordOperators source); 

    List<CallRecordsDto> callRecordsToCallRecordsDtos(List<CallRecords> callRecords); 

} 

public class CallRecordsDto { 

    private String callerNumber; 

    private List<CallRecordOperatorsDto> operators; 

    //getter setters 
} 

public class CallRecordOperatorsDto { 

    private String callRecordsId; 

    private String operatorId; 
    private String operatorName; 

    private String currentTime; 

    // getter setter 

} 

Но выше кода я получаю

{ 
    "callerNumber": "9898989898", 
    "operators": [{ 
     "callRecordsId": null, 
     "operatorId": null, 
     "operatorName": null, 
     "currentTime": null 
    }, { 
     "callRecordsId": null, 
     "operatorId": null, 
     "operatorName": null, 
     "currentTime": null 
    }] 
} 

значения массива оператора равны нулю. что он может решить?

+0

Можете ли вы поделиться определения ваших целевых типов (DTO), а? IIUC, вы хотите отобразить свойства одной из записей в 'A # bs' для свойства в DTO для' A'. Какой это «B»? Ваш лучший подход, вероятно, состоит в том, чтобы использовать выражение для выбора правильного значения: '@Mapping (target =" property1 ", expression =" java (bs.get (0) .property1) ")'. – Gunnar

+0

@ Gunnar обновил вопрос с моей фактической сущностью. Мне нужен список второго объекта в моем первом объекте, как показано выше. – silentprogrammer

ответ

1

Кажется, что ваш не хватает отображения от CallRecordOperators до CallRecordOperatorsDto:

@Mapper 
public interface CallRecordsMapper { 

    CallRecordsMapper INSTANCE = Mappers.getMapper(CallRecordsMapper.class); 

    @Mapping(source="callRecordOperators",target = "operators") 
    CallRecordsDto callRecordsToCallRecordsDto(CallRecords callRecords); 

    @Mapping(target = "callRecordsId", source = "callrecord.id") 
    @Mapping(target = "operatorId", source = "operator.id") 
    @Mapping(target = "operatorName", source = "operator.name") 
    @Mapping(target = "currentTime", source = "startTime") 
    CallRecordOperatorsDto callRecordOperatorsToDto(CallRecordOperators source); 
} 
0

Когда вы делаете запрос на гибернацию A, вы можете получить связанные с ним элементы B коллекции bs, используя различные стратегии. Некоторые из них являются:

  1. Если вы используете HQL построить ваши запросы, вы можете сделать JOIN FETCH или LEFT JOIN FETCH для заполнения bs коллекции:

    String hql = "SELECT DISTINCT a FROM " + A.class.getName() 
        + " a LEFT JOIN FETCH a.bs WHERE ..."; 
    

    Этот запрос будет загружать все данные с помощью одного SQL-запрос.

  2. Использование нетерпеливая выборка из bs коллекции, изменение @OneToMany аннотацию:

    @OneToMany(fetch=FetchType.EAGER) 
    private List<B> bs; 
    

    В этом случае при выполнении запроса из A элементов, запрос SQL будет запущен для извлечения данных A, и для каждого объекта A в результате будет выполнен запрос SQL для загрузки соответствующей коллекции bs.

  3. Если вы используете Criteria для построения запроса, вы можете изменить режим выборки из bs коллекции таким образом, похожий на HQL JOIN FETCH:

    Criteria c = session.createCriteria(A.class); 
    c.setFetchMode("bs", FetchMode.JOIN); 
    c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 
    
0

Как о переходе на несколько иной провер oach, который также работает лучше? Используя Blaze-Persistence Entity Views, вы можете определить свое сопоставление непосредственно на классах DTO и применить это к построителю запросов для генерации эффективных запросов, которые идеально соответствуют вашей структуре DTO.

@EntityView(CallRecords.class) 
public interface CallRecordsDto { 
    // The id of the CallRecords entity 
    @JsonIgnore 
    @IdMapping("id") String getId(); 

    String getCallerNumber(); 

    @Mapping("callRecordOperators") 
    List<CallRecordOperatorsDto> getOperators(); 
} 

@EntityView(CallRecordOperators.class) 
public interface CallRecordOperatorsDto { 

    // The id of the CallRecordOperators entity 
    @JsonIgnore 
    @IdMapping("id") Long getId(); 

    @Mapping("callrecord.id") 
    String getCallRecordId(); 

    @Mapping("operator.id") 
    String getOperatorId(); 

    @Mapping("operator.name") 
    String getOperatorName(); 

    @Mapping("startTime") 
    String getCurrentTime(); 

    // Whatever properties you want 
} 

Посмотрите, как вы можете сопоставить атрибуты сущности прямо в ваших DTO?И тут приходит код для запроса

EntityManager entityManager = // jpa entity manager 
CriteriaBuilderFactory cbf = // query builder factory from Blaze-Persistence 
EntityViewManager evm = // manager that can apply entity views to query builders 

CriteriaBuilder<User> builder = cbf.create(entityManager, CallRecords.class) 
    .where("callerNumber").eq("123456789"); 
List<CallRecordsDto> result = evm.applySetting(
    builder, 
    EntityViewSetting.create(CallRecordsDto.class) 
).getResultList(); 

Обратите внимание, что это будет примерно генерировать следующий оптимизированный запрос

SELECT 
    c.id, 
    c.callerNumber, 
    o.callrecord.id, 
    o.id, 
    o.startTime, 
    op.id, 
    op.name 
FROM CallRecords c 
LEFT JOIN c.callRecordOperators o 
LEFT JOIN o.operator op 
WHERE c.callerNumber = :param_1 
Смежные вопросы