【问题标题】:Join using Hibernate Criteria without using Alias on Restriction使用 Hibernate Criteria 加入而不使用 Alias on Restriction
【发布时间】:2014-09-16 00:22:31
【问题描述】:

我有一个具有 70 个属性的对象。为了便于使用,我创建了 2 个对象,一个“主要”对象和一个“详细信息”对象,基于自动生成的整数 ID 具有 1:1 的关系。我有一个 SEARCH 屏幕,允许搜索任何主要属性,为此我为用户输入的任何内容构建 Restriction 对象。很好的是,我通过遍历字段和构建标准来完成这一切 - 我没有需要丑陋的代码来专门处理 30 个属性中的每一个。

现在他们也想搜索详细信息字段。我以前的屏幕字段迭代代码在没有任何更改的情况下完美运行(使其成为“通用”的全部原因),但是我无法让 JOIN 工作以查询详细信息字段。

class House {
    Integer houseID;
    String address;
    . . .
    HouseDetails houseDetails;
}

class HouseDetails {
    Integer houseID;
    String color;
    . . .
}

我尝试创建一个别名并将其添加到条件中:

criteria.createAlias("houseDetails", "houseDetails");

但我收到此错误:

org.hibernate.QueryException: could not resolve property: color of: House

事情是这样的——我知道如果我在我的限制前面加上别名,这会起作用,但我不想知道该字段来自哪个表(House 或 HouseDetails)。这将破坏所有自动循环代码并为每个字段创建特定代码。

因为只要列名是唯一的,SQL 就可以做到这一点:

select * from house, housedetails where house.houseID = housedetails.houseID 
and color = 'blue';

我想知道如何使用标准使其工作?

顺便说一句,但与此相关:有没有一种方法可以执行 Java 对 Hibernate HBM.XML 映射文件的自省之类的操作?很多次我都想这样做来解决问题,但从未找到答案。对于上述问题,如果我可以很容易地找出每个字段包含在哪个表中,我可以在 Restriction 中添加前缀。像这样:

// Map of search keys (columns) to searching values
for ( String key : parms.keySet() ) {
    String val = parms.get(key);

    if ( HIBERNATE-SAYS-KEY-IS-FROM-DETAILS-TABLE ) {
        key = "houseDetails." + key;            
    }    
    criteria.add(Restrictions.eq(key,val));
}

【问题讨论】:

  • 有什么更新吗?......

标签: java mysql sql hibernate hibernate-criteria


【解决方案1】:

您可以创建方法来查找传递的列名的表名。

通过使用SessionFactory.getClassMetaData(),您可以获得有关该类的所有信息。一旦你有了ClassMetaData,你就可以获得所有的属性名称。下面是一个演示方法:

public String findTableName(String columnName)
{
    boolean found=false;
    Map<String, ClassMetadata> classMetaData =  sessionFactory.getAllClassMetadata();
    for (Entry<String, ClassMetadata> metaData : classMetaData.entrySet()) 
    {
        String[] propertyNames = metaData.getValue().getPropertyNames();                    
        for (String property : propertyNames) 
        {           
            if(property == columnName)
            {
                return metaData.getKey() + "." + property;    
                found=true;
                break;
            }
        }
        if(found)
            break;
    }       
}

【讨论】:

  • 是的,我能够使用 SessionFactory.getClassMetaData() 来获取有关用户想要搜索的列的信息。这有点痛苦,因为我不能简单地在两个表的列上放置一个“aliasName”——只有 Details 表可以有别名。我当然希望有一种方法可以在 Criteria 中制定这个简单的 SQL( select * from house, housedetails where house.houseID = housedetails.houseID and color = 'blue'; ),但显然它无法完成。感谢您的帮助。
【解决方案2】:

hibernate 和 Criteria API 中的别名机制非常明确。我建议稍微阅读一下文档。

我认为你想要的是这样的:

Criteria criteria = session.createCriteria(House.class);
criteria.createAlias("houseDetails.color", "houseColor");
criteria.add(Restrictions.eq("houseColor", "red"));

【讨论】:

  • 不,这行不通。问题是我不想知道“颜色”来自详细信息表。我只知道这两个表之间的列名是唯一的,除了用于连接它们的主键。
猜你喜欢
  • 2015-04-01
  • 2017-03-15
  • 2014-06-21
  • 1970-01-01
  • 2012-01-11
  • 1970-01-01
  • 1970-01-01
  • 2012-09-15
  • 2018-07-24
相关资源
最近更新 更多