JPA (Hibernate), как правильно сделать выборочный подробный левый выбор соединения Мастер-запрос? - PullRequest
0 голосов
/ 02 марта 2020

У меня есть проект JAVA / JPA (реализованный Hibernate). Базовое приложение было сгенерировано с помощью JHIPSTER (затем я настроил его), это отношения:

entity Competence {
    description String required maxlength(200),
}

entity UserCompetenceLevel (user_comp_le) {
     level Integer required
}

relationship ManyToOne {
        UserCompetenceLevel {competence (description)} to Competence,
        UserCompetenceLevel {user (login)} to User
}

Возможно, что у пользователя есть некоторые компетенции, но не все компетенции: я хочу, чтобы, когда я выбираю @GetMapping("/user-competence-levels") Я получаю список всех UserCompetenceLevel, а также «еще не существует» UserCompetenceLevel. Для того проекта, который был определен до того, как он пришел ко мне, я должен использовать внешнее соединение. Hibernate не поддерживает правое соединение, поэтому мне пришлось использовать левое соединение.

Я мог сделать это, работая в @GetMapping("/user-competence-levels"), используя findAllOuterJoinWorking(); в этом ресурсе я выбираю Competence в левом соединении с UserCompetenceLevel как Object[]. Затем я перебираю результат, как вы можете видеть в коде, создавая список UserCompetenceLevel для возврата. Это пример возвращаемого UserCompetenceLevel, когда никого нет для компетенции 13:

{
    "id": null,
    "level": null,
    "competence": {
      "id": 13,
      "description": "react"
    },
    "user": null
  }

Я также сделал ресурс @GetMapping("/user-competence-levels-2nw"), используя List<UserCompetenceLevel> findAllOuterJoin2NotWorking(); Я бы хотел использовать этот способ, но он работает не так, как findAllOuterJoinWorking. Для компетенции 13 я просто получаю null. Можете ли вы помочь мне изменить getAllUserCompetenceLevels() + findAllOuterJoinWorking, чтобы они работали как getAllUserCompetenceLevelsNW() + findAllOuterJoin2NotWorking +?

Другими словами: мне нужна ваша помощь, чтобы изменить findAllOuterJoin2NotWorking, чтобы он не возвращает список массивов объектов, но список UserCompetenceLevel. Мне не нравится приведенная ниже итерация в списке массивов объектов (for (Object[] one : joinList) {....): мне бы хотелось, чтобы hibernate возвращал непосредственно UserCompetenceLevel, правильно внешний соединенный с Competence.

весь соответствующий код:

@Repository
public interface UserCompetenceLevelRepository extends JpaRepository<UserCompetenceLevel, Long> {

    @Query("select u, c  from Competence c LEFT JOIN UserCompetenceLevel  u on u.competence.id=c.id")
    public List<Object[]> findAllOuterJoinWorking();


    @Query("select u  from Competence c LEFT JOIN FETCH UserCompetenceLevel u on u.competence.id=c.id")
    List<UserCompetenceLevel> findAllOuterJoin2NotWorking();
}


@RestController
@RequestMapping("/api")
@Transactional
public class UserCompetenceLevelResource {
@GetMapping("/user-competence-levels")
public List<UserCompetenceLevel> getAllUserCompetenceLevels() {
    //working
     List<Object[]> joinList=userCompetenceLevelRepository.findAllOuterJoinWorking();

     ArrayList<UserCompetenceLevel> returned= new   ArrayList<UserCompetenceLevel>();
     for (Object[] one : joinList) {
         if (one[0] == null) {
             UserCompetenceLevel missingUCL = new UserCompetenceLevel();
             Competence missingCompetence = (Competence) one[1];
             missingUCL.setCompetence(missingCompetence);
             returned.add(missingUCL);
         } else {
             UserCompetenceLevel present = (UserCompetenceLevel) one[0];
             returned.add(present);
         }
     }
    return returned;
}

@GetMapping("/user-competence-levels-2nw")
public List<UserCompetenceLevel> getAllUserCompetenceLevelsNW() {
    //not working
    return userCompetenceLevelRepository.findAllOuterJoin2NotWorking();

}
}


@Entity
@Table(name = "user_comp_le")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class UserCompetenceLevel implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Column(name = "level", nullable = false)
    private Integer level;

    @ManyToOne
    @JsonIgnoreProperties("userCompetenceLevels")
    private Competence competence;

    @ManyToOne
    @JsonIgnoreProperties("userCompetenceLevels")
    private User user;

(...)

}


...