Как сделать так, чтобы отношение «многие ко многим» соединялось и получало первый элемент в конструкторе с критериями jpa? - PullRequest
0 голосов
/ 25 марта 2020

У меня есть 3 класса с двумя отношениями OneToMany и ManyToMany следующим образом:

@Entity
public class Company {
    private Long id;
    private boolean enabled;
    private String tradename;
    //items...

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "company")
    @OrderColumn(name = "address_index")
    private Collection<CompanyAddress> addresses;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "companies_activities", joinColumns = @JoinColumn(name = "company_id", 
               referencedColumnName = "id"), 
    inverseJoinColumns = @JoinColumn(name = "activity_id", referencedColumnName = "id"))
    @OrderColumn(name = "activity_index")
    private Collection<CodeActivity> activities;
}

и

@Entity
public class CompanyAddress {
    //items...
    private String address;

    @ManyToOne
    @JoinColumn(name = "company_id", referencedColumnName = "id", nullable = false)
    private Company company;
}

и 3-й класс:

@Entity
public class CodeActivity {
    //items...
    private String code;

    @ManyToMany(mappedBy = "activities")
    private Collection<Company> companies;
}

Как получить элементы, указанные конструктором критериев? Вот класс с конструктором:

class CurrentCompany {
      //items...

      public CurrentCompany(long id, boolean enabled, String tradename, String address, String code) {
      }
}

И хранилище:

Как объединить эти 3 класса, чтобы восстановить результат в предыдущем классе, зная, что атрибуты адреса и действия списки содержимого в компании, и запрошенный результат представляет собой один элемент (первый) каждый, есть ли возможность восстановить компанию с ее основным адресом и основным кодом деятельности по одной инструкции jpa критерия?

public CurrentCompany getCurrentCompany(final Long companyId) {
     CriteriaBuilder builder = entityManager.getCriteriaBuilder();
     CriteriaQuery<CurrentCompany> criteriaQuery = builder.createQuery(CurrentCompany.class);

     Root<Company> root = criteriaQuery.from(Company.class);
     Join<Company, CodeActivity> activities = root.join("activities", JoinType.INNER);
     Join<Company, CompanyAddress> addresses = root.join("addresses", JoinType.LEFT);

     List<Predicate> predicates = new ArrayList<>();
     predicates.add(builder.equal(root.get("id"), companyId));

     criteriaQuery.multiselect(builder.construct(CurrentCompany.class, root.get("id"), root.get("enabled"), 
                     root.get("tradename"), addresses.get("address"), activities.get("code")));
     criteriaQuery.where(predicates.toArray(new Predicate[0]));

     //Error encountered:
     //org.springframework.dao.InvalidDataAccessApiUsageException: 
     //org.hibernate.hql.internal.ast.QuerySyntaxException:

     //What should I add in order for me to select the first address and activity element?

     return entityManager.createQuery(criteriaQuery).getSingleResult();
}

Спасибо за все ответы!

1 Ответ

0 голосов
/ 25 марта 2020

Я не знаю, правильно ли я понял вопрос, что вы хотите получить первый результат запроса, который будет умножен на N записей и на M в зависимости от количества элементов во второй таблице и третьей Таблица соответственно?

Если это так, я бы попробовал следующее:

 return entityManager.createQuery(criteriaQuery)
      .setFirstResult(0) // set the first result, 0 based
      .setMaxResults(1)  // set the number of recors
      .getResultList();  // you can try getSingleResult() but I prefer to use this in case there are 0 records that do not contain an error
...