【问题标题】:How to use a subquery instead of a joined query to get correct count with hibernate如何使用子查询而不是连接查询来获得正确的休眠计数
【发布时间】:2013-09-15 18:09:43
【问题描述】:

假设我有以下两张桌子(猫和小猫):

==== Cat.java ====
@Id @GeneratedValue( strategy = GenerationType.IDENTITY ) 
private long id;

@Column( unique = true, nullable = false )
private String name;

@OneToMany @JoinColumn( name = "cat_id" )
private List<Kitten> kitten;

==== Kitten.java ====
@Id @GeneratedValue( strategy = GenerationType.IDENTITY ) 
private long id;

@Column( unique = true, nullable = false )
private String name;

以下数据

Cat(id, name)
Cat(1, "Cat 1")
Cat(2, "Cat 2")

Kitten(id, cat_id, name)
Kitten(1, 1, "Kitten 1")
Kitten(2, 1, "Kitten 2")
Kitten(3, 2, "Kitten 3")
Kitten(3, 2, "Bad Kit")

现在我想查看所有猫的名字中都包含“kitten”的小猫。

list = sess().createCriteria( Cat.class ).createAlias( "kitten", "kitten" )
.add( Restrictions.like( "kitten.name", "%kitten%" ) ).list();

前面的命令不是很好,因为加入我会得到重复的条目,例如 count 和 maxresult 不起作用。这是一个有据可查的问题,并提到要使用子查询。

我正在考虑这样的事情(但使用 Criteria-Api):

from Cat where id in
(select cat_id from Kitten where name like '%kitten%')

这是行不通的,因为 hibernate 不允许我访问“cat_id”,而且我不想仅仅为了这个查询而使其双向。

【问题讨论】:

    标签: java hibernate join count hibernate-criteria


    【解决方案1】:

    如果您只是添加一个投影来获取猫 ID,那么您的查询就是您要使用的子查询。所以你只需要以下内容:

    DetachedCriteria acceptedCatIds = DetachedCriteria.forClass(Cat.class);
    acceptedCatIds.createAlias("kitten", "kitten")
                  .add(Restrictions.like("kitten.name", "%kitten%" ))
                  .setProjection(Projections.id());
    
    Criteria acceptedCats = session.createCriteria(Cat.class)
    acceptedCats.add(Subqueries.propertyIn("id", acceptedCatIds));
    

    【讨论】:

      【解决方案2】:

      我强烈建议您也让 Kitten 包含对 Cat 的引用。虽然从小猫和猫的角度来看,需要更多的注意力来保持关系的一致性,但这是值得的。

      class Cat {
      
          @Id @GeneratedValue( strategy = GenerationType.IDENTITY ) 
          private long id;
      
          @OneToMany(mappedBy="parent")
          private List<Kitten> kitten;
      }
      
      class Kitten {
      
          @Id @GeneratedValue( strategy = GenerationType.IDENTITY ) 
          private long id;
      
          @Column( unique = true, nullable = false )
          private String name;
      
          @ManyToOne
          @JoinColumn( name = "cat_id" )
          private Cat parent;
      }
      

      HQL 应该变得和你想要的一样简单:

      from Cat c where c in
      (select parent from Kitten where name like '%kitten%')
      

      甚至

      select distinct parent from Kitten where name like '%kitten%'
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-08
        • 2015-04-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多