Запрос отношения «многие ко многим» с помощью Hibernate Criteria API - PullRequest
2 голосов
/ 06 апреля 2009

У меня есть следующие отношения многие ко многим: File 1 --- * File_Insurer * --- 1 Insurer. Я пытаюсь запросить это отношение, используя Criteria API (Active Record), чтобы получить файлы, которые соответствуют ВСЕМ указанным страховщикам (получить все файлы, где Insurer.Id == 2 AND Insurer.Id == 3).

Сопоставление файлов (частей) :

Файл

[HasAndBelongsToMany(typeof(Insurer),
Table = "Insurer_File", ColumnKey = "IdFile", ColumnRef = "IdInsurer")]
public virtual IList<Insurer> Insurers
{
get { return insurers; }
set { insurers = value; }
}

Страховщик

[HasAndBelongsToMany(typeof(File),
Table = "Insurer_File", ColumnKey = "IdInsurer", ColumnRef = "IdFile")]
public virtual IList<File> Files
{
get { return files; }
set { files = value; }
}

Я пробовал много вариантов :

DetachedCriteria dc = DetachedCriteria.For<File>();
dc.SetResultTransformer(new DistinctRootEntityResultTransformer());
dc.CreateCriteria("Insurers").Add(Expression.Eq("Id", long.Parse("2")));
dc.CreateCriteria("Insurers").Add(Expression.Eq("Id", long.Parse("3")));
List<File> searchResults = File.FindAll(dc).ToList<File>();

Это дает мне ошибку: duplicate association path: Insurers.

Следующая опция :

DetachedCriteria dc = DetachedCriteria.For<File>();
dc.SetResultTransformer(new DistinctRootEntityResultTransformer());
dc.CreateCriteria("Insurers").Add(Expression.And(Expression.Eq("Id", long.Parse("3")), Expression.Eq("Id", long.Parse("2"))));
List<File> searchResults = File.FindAll(dc).ToList<File>();

Список результатов пуст (но не должен быть).

Следующая опция с псевдонимом :

DetachedCriteria dc = DetachedCriteria.For<File>();
dc.SetResultTransformer(new DistinctRootEntityResultTransformer());
dc.CreateAlias("Insurers", "i").Add(Expression.Eq("i.Id", long.Parse("2"))).Add(Expression.Eq("i.Id", long.Parse("3")));
List<File> searchResults = File.FindAll(dc).ToList<File>();

Список результатов снова пуст - странно.

Следующая попытка :

DetachedCriteria dc = DetachedCriteria.For<File>();
dc.SetResultTransformer(new DistinctRootEntityResultTransformer());
List<long> insurerIds = new List<long>();
insurerIds.Add(2);
insurerIds.Add(3);
dc.CreateCriteria("Insurers").Add(Expression.In("Id", insurerIds));
List<File> searchResults = File.FindAll(dc).ToList<File>();

Это работает как-то, но набор результатов содержит все возможные параметры (ИЛИ) - это не точное совпадение.

1 Ответ

0 голосов
/ 18 апреля 2009

Это было уже ответил - см. Мое мнение об этом ниже. Сайт в спящем режиме, похоже, не работает, но посмотрите этот экземпляр главы 11 HQL руководства пользователя Hibernate.

public List<Files> findFilesForInsurers(Insurer... insurers) {
    StringBuilder hql = new StringBuilder();
    hql.append("select f from Files ff where 1=1 ");
    for (int i = 0; i < insurers.length; i++) {
        hql.append(String.format(" and :i%d in elements(ff.insurers)", i));
    }
    Query query = getSession().createQuery(hql.toString());
    for (int i = 0; i < insurers.length; i++) {
        query.setParameter("i" + i, insurers[i]);
    }
    return query.list();
}

Предоставление HQL следующим образом:

select f from Files ff where 1=1
    and :i1 in elements(ff.insurers)
    and :i2 in elements(ff.insurers)

Я подозреваю, что SQL, который вы пытаетесь получить, выглядит примерно так, хотя я не могу сказать вам точно во что переводится вышеупомянутый HQL ...

select f.* from files f
    left outer join files_insurers fi1 on fi1.files_id = f.id
    left outer join files_insurers fi2 on fi2.files_id = f.id
where 1 = 1
    and fi1.insurers_id = :i1
    and fi2.insurers_id = :i2;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...