2016-08-13 3 views
0

Моя проблема немного сложнее, чем описано с первого взгляда. Позвольте мне попытаться объяснить. У меня есть два объекта с однонаправленной связью ManyToMany:JPA Сортировать по столбцу во многих отношениях

public class Category implements Serializable { 

    @Id 
    @Column(name = "ct_id") 
    @SequenceGenerator(name = "category_ct_id_seq", sequenceName = "category_ct_id_seq", allocationSize = 1) 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "category_ct_id_seq") 
    private Long id; 

    @Column(name = "ct_name_key") 
    private String nameKey; 

    @ManyToMany 
    @JoinTable(name = "category_2_country", 
      joinColumns = @JoinColumn(name = "c2c_category_id"), 
      inverseJoinColumns = @JoinColumn(name = "c2c_country_id")) 
    private Set<Country> countries; 
} 

public class Country { 

    @Id 
    @SequenceGenerator(name = "country_c_id_seq", sequenceName = "country_c_id_seq", allocationSize = 1) 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "country_c_id_seq") 
    @Column(name = "c_id") 
    private Long id; 

    @Column(name = "c_name") 
    private String name; 

    @Column(name = "c_iso_2_alpha") 
    private String isoAlpha2Code; 

И я извлекая коллекцию Категории по коде ISO страны (на самом деле, все категории, которая имеет отношение с запрашиваемой страной). Для этого я написал a Спецификация:

public class CategorySpecification implements Specification<Category> { 

    Country matchCountry; 

    @Override 
    public Predicate toPredicate(Root<Category> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder builder) { 

     return builder.isMember(matchCountry, root.get("countries")); 

    } 
} 

Это работает очень хорошо. Проблема в том, что мне нужно иметь приоритет заказов для категорий в каждой стране. Переходный стол выглядит так: enter image description here Так что, когда я получаю подборку категорий для данной страны, я хочу, чтобы она была заказана в соответствии с этой колонкой sort_order.

Соответствующий SQL-запрос выглядит так, как это вещь:

SELECT * 
FROM category 
    JOIN category_2_country ON category.ct_id = category_2_country.c2c_category_id 
WHERE c2c_country_id = ? 
ORDER BY sort_order; 

Но как я должен сделать это в моих JPA сущностей? И как я должен сохранять его обратно в базу данных, этот порядок нужно динамически изменять (например, с панели администратора)?

Редакцией: таблиц в базе данных, соответствующих субъектов:

Один для Страна Country

И One для Категория:

, всего редактировалось 2: Я удалось добиться желаемого поведения с помощью нативного запроса следующим образом:

@Repository 
public interface CategoryRepository extends JpaRepository<Category, Long>, JpaSpecificationExecutor<Category> { 

    @Query(value = "SELECT ct.*\n" + 
      "FROM category ct\n" + 
      " JOIN category_2_country c2c ON ct.ct_id = c2c.c2c_category_id\n" + 
      " JOIN country c ON c2c.c2c_country_id = c.c_id\n" + 
      "WHERE c.c_iso_2_alpha = :countryIso\n" + 
      "ORDER BY c2c.sort_order", nativeQuery = true) 
    List<Category> findCategoriesForCountryOrdered(@Param("countryIso") String countryIso); 
} 

Но все-таки надеюсь, что иметь больше JPA/Hibernate способ сделать эту вещь

+1

[Это] (http://stackoverflow.com/questions/5127129/mapping-many-to-many-association-table-with-extra-columns) может быть полезно. –

+0

Я видел эту ветку раньше, но все же надеюсь иметь более простое решение, чем рефакторинг всех объектов только из-за столбца приоритета – DruidKuma

ответ

1

Как вы используете спецификации вы используете JpaRepository с JpaSpecificationExecutor. JpaSpecificationExecutor api дает нам метод findAll(Specification<T> spec, Sort sort).

Используя класс Sort, вы можете указать, по каким свойствам (и направлениям) вы хотите отсортировать список результатов.

Вот документы: Sort

EDIT: После некоторых поисков - к сожалению, без отображения таблицы объединения в спящий режим, вы не можете заказать по/сортировать sort_order недвижимость. Это связано с JPQL, который может работать только с отображаемыми свойствами в объектах - он не может достигнуть таблиц в БД, если вы их не сопоставляете.

Итак, вы можете сопоставить таблицу ассоциаций и создать спецификацию, которая объединяет эти две таблицы и создает сортировку по sort_order.

+0

Спасибо за хороший ответ. Но я не могу передать Сорт только имя столбца БД.Это должно быть свойство любой категории или страны, но не имя столбца во многих таблицах. Может быть, у меня нет никаких опций, вместо того, чтобы превратить мою таблицу ManyToMany в отдельный объект? :( – DruidKuma

+0

Вы должны передать имена переменных из сопоставленных объектов. В вашем примере это будет: 'countries.sortOrder', предполагая, что класс' Country' имеет 'sortOrder'. Это правда? – ByeBye

+0

Это не так, к сожалению. SortOrder специфичен не для страны, а для сопоставления категории Категория. – DruidKuma

Смежные вопросы