Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
527 views
in Technique[技术] by (71.8m points)

sql - Hibernate Create Criteria to join the same table twice - tried 2 approach with 2 difference error

I would like to create create criteria for the following native sql.

Unfortunately, I hit error of duplicate associate path when use createCriteria twice. When I try to use Restrictions.sqlRestriction. It unable provide the SQL that I want.

Try 1: Create Criteria - duplicate associate path

 Criteria criteria = getSession().createCriteria( Company.class );
                 criteria.createAlias( "customerCategories", "c1" );
                 criteria.add( Restrictions.in( "c1.customerCategory.customerCategoryId",
                         company.getBaseCustomerCategoryId() ) );
                 criteria.createAlias( "customerCategories", "c2" );
                 criteria.add( Restrictions.in( "c2.customerCategory.customerCategoryId",
                         company.getPromoCustomerCategoryId() ) );

Try 2: Create SQL Restriction - ORA-00920: invalid relational operator because of "where"

  Criteria criteria = getSession().createCriteria( Company.class );
                 criteria.add( Restrictions.sqlRestriction(
                         "INNER JOIN Company_Customercategory a on {alias}.companyId = a.companyId and a.CUSTOMERCATEGORYID = ?",
                         company.getBaseCustomerCategoryId(), LongType.INSTANCE ) );
                 criteria.add( Restrictions.sqlRestriction( 
                         "1=1 INNER JOIN Company_Customercategory b on {alias}.companyId = b.companyId
 and b.CUSTOMERCATEGORYID = ?", 
                         company.getPromoCustomerCategoryId(), LongType.INSTANCE) );

Wrong Result

select this_.* from Companies this_ where 
  INNER JOIN Company_Customercategory a 
  on this_.companyId = a.companyId 
  and a.CUSTOMERCATEGORYID = 1
  and 1=1 INNER JOIN Company_Customercategory b 
  on this_.companyId = b.companyId 
  and b.CUSTOMERCATEGORYID = 6

Expected SQL

select * from companies c
  inner join Company_Customercategory a
  on c.companyId = a.companyId
  and a.CUSTOMERCATEGORYID = 1
  inner JOIN Company_Customercategory b
  on a.companyId = b.companyId
  and b.CUSTOMERCATEGORYID = 6

Appreciate your help. Thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There is an old Hibernate bug HHH-879 on the problem of org.hibernate.QueryException: duplicate association path opened 2005 and still open...

Other issue is closed without solution HHH-7882

So the option 1) is rather not suitable.

But in the comments of the above bug an usefull workaround is mentioned using exists

So use twice sqlRestriction with exists and a correlated subquery filtering the propper category. You will get only companies connected to both categories.

crit.add( Restrictions.sqlRestriction( 
  "exists (select null from Company_Customercategory a where {alias}.company_Id = a.company_Id and a.CUSTOMERCATEGORYID = ?)",
  1, IntegerType.INSTANCE ) );
crit.add( Restrictions.sqlRestriction( 
  "exists (select null from Company_Customercategory a where {alias}.company_Id = a.company_Id and a.CUSTOMERCATEGORYID = ?)",
  6, IntegerType.INSTANCE ) );

This leads to the following query which provides the correct result

select this_.COMPANY_ID as COMPANY_ID1_2_0_, this_.COMPANY_NAME as COMPANY_NAME2_2_0_ 
from COMPANIES this_ 
where exists (select null from Company_Customercategory a 
              where this_.company_Id = a.company_Id and a.CUSTOMERCATEGORYID =  ?) and 
      exists (select null from Company_Customercategory a 
              where this_.company_Id = a.company_Id and a.CUSTOMERCATEGORYID = ?)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...