10

我不确定如何描述这个问题,所以我认为一个例子是问我问题的最佳方式:

我有两个具有多对多关系的表:

DriversLicence <-> LicenseClass

LicenceClass 是“汽车”、“摩托车”和“中刚性”之类的东西。

使用 Hibernate Criteria,我如何找到同时具有“汽车”和“摩托车”LicenceClasses 的所有许可证?

更新 12/11/2008 我发现这可以通过使用自定义 ResultTransformer 轻松实现。然而问题是结果转换器仅在查询返回其结果后应用,它实际上并没有成为 SQL 的一部分。所以我想我现在的问题是“你能做我最初在 SQL 中描述的事情吗?是否有 Hibernate Criteria 模拟?”

4

5 回答 5

6

这是我最终使用 HQL 实现它的方法:

public List<DriversLicence> findDriversLicencesWith(List<LicenceClass> licenceClasses) {
    String hqlString = "select dl from DriversLicenceImpl dl where 1=1 ";
    for (int i = 0; i < licenceClasses.size(); i++) {
        hqlString += " and :licenceClass" + i + " = some elements(dl.licenceClasses)";
    }

    Query query = getSession().createQuery(hqlString);
    for (int i = 0; i < licenceClasses.size(); i++) {
        query.setParameter("licenceClass" + i, licenceClasses.get(i));
    }
    return query.list();
}

或者使用带有 sqlRestriction 的 Hibernate Criteria:

for (LicenceClass licenceClass : licenceClasses) {               
    criteria.add(Restrictions.sqlRestriction("? = some(select " + LicenceClass.PRIMARY_KEY + " from " +
                    LICENCE_CLASS_JOIN_TABLE + "  where {alias}." +
                    DriversLicence.PRIMARY_KEY + " = " + DriversLicence.PRIMARY_KEY + ")",
                    licenceClass.getId(), Hibernate.LONG));
}

LICENCE_CLASS_JOIN_TABLE 是 hibernate 生成的表的名称,用于支持 driversLicence 和 LicenceClass 之间的多对多关系。

于 2008-11-23T22:22:29.593 回答
0

您仍然可以使用点符号来处理关系。例如,假设您有 DriversLicence.licenceClass 属性和 LicenceClass.type 属性,则:

session.createCriteria(DriversLicence.class)
   .add(Expression.or(
     Expression.eq("licenceClass.type", "Car"),
     Expression.eq("licenceClass.type", "Motorbike")
   )
).list();

不过就个人而言,我只是避免在这种情况下使用条件,因为它不是动态查询,而是使用:

session.createQuery("from DriversLicence where licenceClass.type in (:types)")
  .setParameterList("types", myListOfTypes)
  .list();
于 2008-11-05T05:44:07.143 回答
0

我有一个类似的问题,但使用 HQL 进行了修复,我有一个与“用户”类相关的“企业”类,也与“角色”类相关,当我需要所有相关的企业时,它们具有多对多的关系对于特定用户,我执行以下操作;

Select e from Enterprise As e inner join e.Users As u inner join u.Roles As r 
Where u.UserCode=?

我想在你的情况下你应该做类似的事情;

Select dl from LicenceClass As l inner join l.DriversLicences As dl
Where 
l.LicenseClass.Name = ? OR 
l.LicenseClass.Name=? OR 
l.LicenseClass.Name=?

希望能帮助到你。

于 2008-11-12T03:12:13.843 回答
0

另一种选择是链式连接(每个 LicenseClass 一个连接)。我使用了这样的标准构建器和谓词

 List<Predicate> predicates = new ArrayList<>();
 for(Integer lcId : licenceClassIdList) {
     SetJoin<DriversLicence, LicenceClass> dlClasses = dlRoot.join(DriversLicence_.licenceClasses);
     predicates.add(builder.equal(dlClasses.get(LicenseClass_.id), lcId));
 }
 Predicate predicate = builder.and(predicates.toArray(new Predicate[predicates.size()]));

注意 dlRoot 是 Root 类的对象,您可以从 CriteriaQuery 类中获取它。结果谓词是您要查找的内容...

于 2016-10-04T12:13:13.323 回答
-1

“我认为这不会奏效。我想查找同时具有“汽车”和“摩托车”的所有许可证

用户 Expression.and(....) 而不是 Expression.or(....) 在 Nick 提供的代码段中

于 2008-11-07T08:48:58.173 回答