使用Hibernate Criteria API查询多对多关系

时间:2009-04-06 18:09:58

标签: hibernate activerecord nhibernate

我有以下多对多关系:File 1 --- * File_Insurer * --- 1 Insurer。我正在尝试使用Criteria API(Active Record)查询此关系,以获取符合所有指定保险公司的文件(获取Insurer.Id == 2Insurer.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>();

这会以某种方式工作,但结果集包含所有可能的选项(OR) - 它不是完全匹配。

1 个答案:

答案 0 :(得分:0)

这是answered already - 请参阅下面我对此的看法。 hibernate网站似乎已关闭,但请查看Hibernate用户指南第11章HQL的副本。

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;