根据有关Hibernate中多对多映射的特定条件检索行

时间:2012-11-14 19:33:28

标签: spring hibernate jsp oracle10g hql

我只是复制&从one of my questions粘贴了一些介绍性文本,因为同样的表格关系也包含在这个问题中。


我在Oracle(10g)数据库中有三个表,如下所示。我正在使用Hibernate Tools 3.2.1.GA和Spring 3.0.2版。

  1. 产品 - 父表
  2. 颜色 - 父表
  3. ProductColour - 加入表格 - 分别引用colourIdprodIdColourProduct
  4. ProductColourProductColour之间的联接表。正如表名所暗示的那样,ProductColour之间存在多对多关系,由PrductColour映射。我认为,数据库中的关系很容易想象,只有这么多信息才能清楚。因此,我不会不必要地探讨这种关系。

    Product中的实体(行)与Colour中的任意数字实体相关联,Colour中的实体(行)也可以与{Product中的任意数量的实体相关联1}}。


    因为它是多对多关系,所以它在ProductColour实体类(POJO)中映射到它们各自的java.util.Set并且没有直接的POJO类可以使用product_colour表。

    班级Product如下所示。

    public class Product  implements java.io.Serializable 
    {
        private BigDecimal prodId;
        private Set<Colour> colours = new HashSet<Colour>(0);
    
        .
        .
        .
    
        //Other properties with setters and getters. 
    }
    

    班级Colour如下所示。

    public class Colour implements java.io.Serializable 
    {
        private BigDecimal colourId;
        private Set<Product> products = new HashSet<Product>(0);
    
        .
        .
        .
    
        //Other properties with setters and getters. 
    }
    

    实体之间的实际映射可以在xxx.hbm.xml个文件中找到,关于这个问题,我认为这是不必要的。


    我想要做的是只检索Colour表格中与某一特定产品的ProductColour中的颜色行不匹配的行。在这方面,本机Oracle SQL语句看起来如下所示。

    SELECT colour_id, colour_name, colour_hex
    FROM colour
    WHERE colour_id not in (SELECT colour_id FROM product_colour WHERE prod_id=81)
    ORDER BY colour_id DESC
    

    其中prod_id可以是Java中任何有效的BigDecimal个动态数字。

    如前所述,该关系在Hibernate中以多对多关系的形式提供,数据库表product_colour没有POJO类可用,因此,我在编写这样的HQL语句时遇到了麻烦休眠。我曾尝试编写这样的HQL语句,但没有尝试成功。


    [部分其余部分提供的代码可能完全没有必要审查]

    因此我遵循传统方式。我正在做的是......我首先根据动态值ProductprodId实体类中检索单个产品行,例如,

    List<Product>list=session.createQuery("from Product where prodId=:prodId")
                      .setParameter("prodId", prodId).list();
    

    然后使用循环,我得到整个Colour集合 - java.util.Set对应于Oracle中的product_colour表,Product实体中可用这个产品如,

    Set<Colour>colours=new HashSet<Colour>(0);
    
    for(Product p:list)
    {
        if(p!=null)
        {               
            colours=p.getColours();
        }
    }
    

    可以看出,colours Set正在填充Oracle中product_colour表中可用的所有颜色行(参考行)。

    获取所有这些行之后,我得到了整个Colour实体类本身(其中的所有行),它对应于Oracle中的colour表,然后删除那些匹配的行从product_colour Oracle表中检索到的行(在前面代码段中的colours中可用),满足前面提到的条件,例如,

    List<Colour>colourList=session.createQuery("from Colour order by colourId desc").list();
    Iterator<Colour>it=colourList.iterator();        
    
    while(it.hasNext())
    {
        Colour c=(Colour)it.next();
        for(Colour pc:colours)     //colours is available in the preceding snippet.
        {
            if(c==pc)
            {
                it.remove();
            }
        }
    }
    

    这可以做到预期的但是这样做可能意味着系统的一些开销。此外,这种分页的方法似乎无法实现我想要实现的目标。我不能使用setFirstResult(int)setMaxResults(int)方法来完成分页任务,否则就像下面显示的Product实体类一样,

    List<Product> products=session.createQuery("from product order by prodId desc")
                           .setMaxResults(0).setFirstResult(4); 
    

    所以问题又是,关于这种关系,是否可以编写这样一个HQL语句,它只能检索Colour实体类中与那些不匹配的那些行product_colour Oracle表中的颜色行与上面显示的本机SQL语句类似

    如何实现分页的概念(如果不可能)?

1 个答案:

答案 0 :(得分:1)

对一个长期问题的简短回答:

select colour from Colour colour 
where colour.id not in (
    select colour2.id from Product product
    inner join product.colours colour2
    where product.id = :productId)