2015-08-26 2 views
0

Я создал список документов с тегами, со многими отношениями между тегами и документами. Теперь я хотел бы использовать механизм критериев спящего режима для запроса «сводки» каждого тега, который включает в себя подсчет того, как часто использовался конкретный тег, с дополнительным ограничением на то, был ли опубликован этот документ.Ограничение соединения слева от гибернации в отношениях «многие ко многим»

Субъектами Я использую примерно выглядеть следующим образом (Вы заметите SQL-таблицу соединения в середине есть):

@Entity 
public class DocumentTag { 

    ... various things ... 

    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "tags") 
    private List<Document> documents = new ArrayList<>(); 

} 

@Entity 
public class Document { 

    ... various things ... 

    @Basic 
    @Column(name = "published", columnDefinition = "BIT", length = 1) 
    protected boolean published = false; 

    @ManyToMany(fetch = FetchType.LAZY) 
    @JoinTable(name = "document_tag_joins", 
      uniqueConstraints = @UniqueConstraint(
        columnNames = {"document", "tag"} 
      ), 
      joinColumns = {@JoinColumn(name = "document")}, 
      inverseJoinColumns = {@JoinColumn(name = "tag")}) 
    private List<DocumentTag> tags = new ArrayList<>(); 

} 

Учитывая вышесказанное, мне удалось выяснить, что строительство запрос должен работать более или менее следующим образом:

Criteria c = session.createCriteria(DocumentTag.class); 

c.createAlias("documents", "docs", 
     JoinType.LEFT_OUTER_JOIN, 
     Restrictions.eq("published", true) 
); 

c.setProjection(
     Projections.projectionList() 
       .add(Projections.alias(Projections.groupProperty("id"), "id")) 
       .add(Projections.alias(Projections.property("createdDate"), "createdDate")) 
       .add(Projections.alias(Projections.property("modifiedDate"), "modifiedDate")) 
       .add(Projections.alias(Projections.property("name"), "name")) 
       .add(Projections.countDistinct("docs.id"), "documentCount")); 

// Custom response entity mapping 
c.setResultTransformer(
     Transformers.aliasToBean(DocumentTagSummary.class) 
); 

List<DocumentTagSummary> results = c.list(); 

Учитывая вышеизложенное, спящий режим генерируется SQL-запрос выглядит следующим образом:

SELECT 
    this_.id    AS y0_, 
    this_.createdDate  AS y1_, 
    this_.modifiedDate  AS y2_, 
    this_.name    AS y3_, 
    count(DISTINCT doc1_.id) AS y5_ 
FROM tags this_ 
    LEFT OUTER JOIN tag_joins documents3_ 
    ON this_.id = documents3_.tag AND (doc1_.published = ?) 
    LEFT OUTER JOIN documents doc1_ 
    ON documents3_.document = doc1_.id AND (doc1_.published = ?) 
GROUP BY this_.id 

Как вы можете видеть выше, ограничение публикации применяется к обоим левым внешним соединениям. Я не уверен, что это по дизайну, однако мне нужно, чтобы опубликованное ограничение применялось ТОЛЬКО ко второму левому внешнему соединению.

Любые идеи?

ответ

0

Мне удалось обойти эту проблему, придя к ней сбоку. Во-первых, мне пришлось изменить «опубликованный» столбец, чтобы использовать целое число, а не бит. Тогда я был в состоянии немного изменить проекцию результата следующим образом:

// Start building the projections 
    ProjectionList projections = 
      Projections.projectionList() 
        .add(Projections.alias(
          Projections.groupProperty("id"), "id")) 
        .add(Projections.alias(
          Projections.property("createdDate"), 
          "createdDate")) 
        .add(Projections.alias(
          Projections.property("modifiedDate"), 
          "modifiedDate")) 
        .add(Projections.alias(
          Projections.property("name"), "name")); 

    if (isAdmin()) { 
     // Give the raw count. 
     projections.add(Projections.countDistinct("docs.id"), "documentCount"); 
    } else { 
     // Use the sum of the "published" field. 
     projections.add(Projections.sum("docs.published"), "documentCount"); 
    } 

Я признаю, что это на самом деле не отвечает на вопрос о том, почему спящий режим критериев ограничений на многие-ко-многим таблицам получить применяется ко всем таблицам , но он решил мою проблему.

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