title: Why does Hibernate generate a CROSS JOIN for an implicit join of a @ManyToOne association?
body: <p>Baur &amp; King said in their book:</p>
  <blockquote>
  <p>Implicit joins are always directed along many-to-one or one-to-one association, never through a collection-valued association.</p>
  <p>[P 646, Ch 14]</p>
  </blockquote>
  <p>But when I am doing that in the code it is generating a CROSS JOIN instead of an INNER JOIN.</p>
  <p>Mapping is from <code>Member2</code> (many-to-one) -&gt; <code>CLub</code>.</p>
  <p>But <code>Club2</code> has no information about members and <code>Member2</code> is having a Foreign Key of Club2.</p>
  <p>My query is</p>
  <pre><code>// Implicit: Find all UK club member who is female
  Transaction t1 = HibernateUtil.begin();
  Query query =
      HibernateUtil.getSession().createQuery(&quot;From Member2 m where m.club2.country = 'UK' &quot;);
  List&lt;Member2&gt; memList = query.list();
  for (Member2 m : memList)
    System.out.println(m);
  HibernateUtil.end(t1);
  </code></pre>
  <p>And, Hibernate is generating the following SQL query:</p>
  <pre><code>Hibernate: 
      select
          member2x0_.member_id as member_i1_1_,
          member2x0_.club_id as club_id5_1_,
          member2x0_.member_age as member_a2_1_,
          member2x0_.member_name as member_n3_1_,
          member2x0_.member_sex as member_s4_1_ 
      from
          TBL_MEMBER2 member2x0_ cross 
      join
          TBL_CLUB2 club2x1_ 
      where
          member2x0_.club_id=club2x1_.club_id 
          and club2x1_.country='UK'
  Hibernate: 
      select
          club2x0_.club_id as club_id1_0_0_,
          club2x0_.club_name as club_nam2_0_0_,
          club2x0_.country as country3_0_0_ 
      from
          TBL_CLUB2 club2x0_ 
      where
          club2x0_.club_id=?
  aaa 25 m
  bbb 28 f
  </code></pre>
  <p>Club2.java</p>
  <pre><code>package com.lilu.de.onetomany.uni.other;
  
  import javax.persistence.Entity;
  import javax.persistence.GeneratedValue;
  import javax.persistence.GenerationType;
  import javax.persistence.Id;
  import javax.persistence.SequenceGenerator;
  import javax.persistence.Table;
  
  @Entity
  @Table(name = &quot;TBL_CLUB2&quot;)
  public class Club2 {
  
    @GeneratedValue(generator = &quot;pkey_Club2&quot;, strategy = GenerationType.SEQUENCE)
    @SequenceGenerator(name = &quot;pkey_Club2&quot;, initialValue = 1000, allocationSize = 10,
        sequenceName = &quot;seq_pkey_Club2&quot;)
    @Id
    private int club_id;
  
    private String club_name;
  
    private String country;
  
    // private Set Member2 = new HashSet();
  
    public Club2() {
      super();
    }
  
    public Club2(String cname, String ccountry) {
      this.club_name = cname;
      this.country = ccountry;
    }
  
    @Override
    public String toString() {
      String temp = club_name + &quot; &quot; + country + &quot; &quot;;
      // Iterator&lt;Member2&gt; iter = Member2.iterator();
      // String mems = null;
      // while (iter.hasNext()) {
      // mems += iter.next();
      // }
      // temp += &quot;\n&quot; + mems;
      return temp;
    }
  
    public int getClub_id() {
      return club_id;
    }
  
    public void setClub_id(int club_id) {
      this.club_id = club_id;
    }
  
    public String getClub_name() {
      return club_name;
    }
  
    public void setClub_name(String club_name) {
      this.club_name = club_name;
    }
  
    public String getCountry() {
      return country;
    }
  
    public void setCountry(String country) {
      this.country = country;
    }
  
    /*
     * public Set&lt;Member2&gt; getMember2() { return Member2; }
     * 
     * public void setMember2(Set&lt;Member2&gt; Member2) { this.Member2 = Member2; }
     */
  }
  </code></pre>
  <p>Member2.java</p>
  <pre><code>package com.lilu.de.onetomany.uni.other;
  
  import javax.persistence.CascadeType;
  import javax.persistence.Entity;
  import javax.persistence.GeneratedValue;
  import javax.persistence.GenerationType;
  import javax.persistence.Id;
  import javax.persistence.JoinColumn;
  import javax.persistence.ManyToOne;
  import javax.persistence.SequenceGenerator;
  import javax.persistence.Table;
  
  @Entity
  @Table(name = &quot;TBL_MEMBER2&quot;)
  public class Member2 {
  
    @GeneratedValue(generator = &quot;pkey_member2&quot;, strategy = GenerationType.SEQUENCE)
    @SequenceGenerator(name = &quot;pkey_member2&quot;, sequenceName = &quot;seq_pkey_member2&quot;)
    @Id
    private int member_id;
  
    private String member_name;
  
    private int member_age;
  
    private char member_sex;
  
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = &quot;club_id&quot;)
    private Club2 club2;
  
    public Member2() {
      super();
    }
  
    public Member2(String mname, int age, char sex) {
      this.member_name = mname;
      this.member_age = age;
      this.member_sex = sex;
    }
  
    public Club2 getClub2() {
      return club2;
    }
  
    public void setClub2(Club2 club2) {
      this.club2 = club2;
    }
  
    @Override
    public String toString() {
      return member_name + &quot; &quot; + member_age + &quot; &quot; + member_sex;
    }
  
    public String getMember_name() {
      return member_name;
    }
  
    public void setMember_name(String member_name) {
      this.member_name = member_name;
    }
  
    public int getMember_age() {
      return member_age;
    }
  
    public void setMember_age(int member_age) {
      this.member_age = member_age;
    }
  
    public char getMember_sex() {
      return member_sex;
    }
  
    public void setMember_sex(char member_sex) {
      this.member_sex = member_sex;
    }
  
    public int getMember_id() {
      return member_id;
    }
  
    public void setMember_id(int member_id) {
      this.member_id = member_id;
    }
  
  }
  </code></pre>
  <p>hibernate.cfg.xml</p>
  <pre><code>&lt;?xml version='1.0' encoding='utf-8'?&gt;
  &lt;!--
    ~ Hibernate, Relational Persistence for Idiomatic Java
    ~
    ~ Copyright (c) 2010, Red Hat Inc. or third-party contributors as
    ~ indicated by the @author tags or express copyright attribution
    ~ statements applied by the authors.  All third-party contributions are
    ~ distributed under license by Red Hat Inc.
    ~
    ~ This copyrighted material is made available to anyone wishing to use, modify,
    ~ copy, or redistribute it subject to the terms and conditions of the GNU
    ~ Lesser General Public License, as published by the Free Software Foundation.
    ~
    ~ This program is distributed in the hope that it will be useful,
    ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    ~ or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
    ~ for more details.
    ~
    ~ You should have received a copy of the GNU Lesser General Public License
    ~ along with this distribution; if not, write to:
    ~ Free Software Foundation, Inc.
    ~ 51 Franklin Street, Fifth Floor
    ~ Boston, MA  02110-1301  USA
    --&gt;
  &lt;!DOCTYPE hibernate-configuration PUBLIC
          &quot;-//Hibernate/Hibernate Configuration DTD 3.0//EN&quot;
          &quot;http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd&quot;&gt;
  
  &lt;hibernate-configuration&gt;
  
      &lt;session-factory&gt;
  
          &lt;!-- Database connection settings --&gt;
          &lt;property name=&quot;connection.driver_class&quot;&gt;org.postgresql.Driver&lt;/property&gt;
          &lt;property name=&quot;connection.url&quot;&gt;jdbc:postgresql://localhost:5432/hibernatedb1&lt;/property&gt;
          &lt;property name=&quot;connection.username&quot;&gt;postgres&lt;/property&gt;
          &lt;property name=&quot;connection.password&quot;&gt;ani155&lt;/property&gt;
  
          &lt;!-- JDBC connection pool (use the built-in) --&gt;
          &lt;property name=&quot;connection.pool_size&quot;&gt;1&lt;/property&gt;
  
          &lt;!-- SQL dialect --&gt;
          &lt;property name=&quot;dialect&quot;&gt;org.hibernate.dialect.PostgreSQLDialect&lt;/property&gt;
  
          &lt;!-- Disable the second-level cache  --&gt;
          &lt;property name=&quot;cache.provider_class&quot;&gt;org.hibernate.cache.internal.NoCacheProvider&lt;/property&gt;
  
          &lt;!-- Echo all executed SQL to stdout --&gt;
          &lt;property name=&quot;show_sql&quot;&gt;true&lt;/property&gt;
          &lt;property name=&quot;format_sql&quot;&gt;true&lt;/property&gt; 
  
          &lt;!-- Drop and re-create the database schema on startup --&gt;
          &lt;property name=&quot;hbm2ddl.auto&quot;&gt;update&lt;/property&gt;
  
          &lt;!-- Names the annotated entity class --&gt;
          &lt;mapping class=&quot;com.lilu.de.onetomany.uni.other.Club2&quot;/&gt;
          &lt;mapping class=&quot;com.lilu.de.onetomany.uni.other.Member2&quot;/&gt;
         &lt;!--   &lt;mapping class=&quot;com.apal.mapping.onetoone.User&quot;/&gt; --&gt;
      &lt;/session-factory&gt;
  
  &lt;/hibernate-configuration&gt;
  </code></pre>
  <p>Test.java</p>
  <pre><code>package com.lilu.de.onetomany.uni.other;
  
  import java.util.List;
  
  import org.hibernate.Query;
  import org.hibernate.Session;
  import org.hibernate.SessionFactory;
  import org.hibernate.Transaction;
  import org.hibernate.cfg.Configuration;
  
  public class Test {
    public static void main(String[] args) {
  
      Test test = new Test();
      // test.setup();
      test.SelectQuery1Implicit();
      // test.SelectQuery2ExplicitFromClause();
      // test.SelectQuery3JoinFetch();
      // test.SelectQuery4ThetaJoin();
    }
  
    private void SelectQuery1Implicit() {
      // Implicit: Find all UK club member who is female
      Transaction t1 = HibernateUtil.begin();
      Query query =
          HibernateUtil.getSession().createQuery(&quot;From Member2 m where m.club2.country = 'UK' &quot;);
      List&lt;Member2&gt; memList = query.list();
      for (Member2 m : memList)
        System.out.println(m);
      HibernateUtil.end(t1);
    }
  
    private void setup() {
      Transaction t1 = HibernateUtil.begin();
      Club2 c1 = new Club2(&quot;MulaRougne&quot;, &quot;UK&quot;);
      Member2 m1 = new Member2(&quot;aaa&quot;, 25, 'm');
      Member2 m2 = new Member2(&quot;bbb&quot;, 28, 'f');
      m1.setClub2(c1);
      m2.setClub2(c1);
      HibernateUtil.getSession().save(c1);
      HibernateUtil.getSession().save(m1);
      HibernateUtil.getSession().save(m2);
      Club2 c2 = new Club2(&quot;Queen's Club&quot;, &quot;UK&quot;);
      Club2 c3 = new Club2(&quot;Disney&quot;, &quot;USA&quot;);
      Member2 m3 = new Member2(&quot;ccc&quot;, 32, 'm');
      Member2 m4 = new Member2(&quot;ddd&quot;, 23, 'm');
      m3.setClub2(c3);
      m4.setClub2(c3);
      HibernateUtil.getSession().save(m3);
      HibernateUtil.getSession().save(m4);
      HibernateUtil.getSession().save(c2);
      HibernateUtil.getSession().save(c3);
  
  
      /*
       * Club2 c1 = new Club2(&quot;MulaRougne&quot;, &quot;UK&quot;); Club2 c2 = new Club2(&quot;Queen's Club&quot;, &quot;UK&quot;); Club2
       * c3 = new Club2(&quot;Disney&quot;, &quot;USA&quot;);
       * 
       * Member2 m1 = new Member2(&quot;aaa&quot;, 25, 'm'); Member2 m2 = new Member2(&quot;bbb&quot;, 28, 'f'); Member2
       * m3 = new Member2(&quot;ccc&quot;, 32, 'm'); Member2 m4 = new Member2(&quot;ddd&quot;, 23, 'm'); Member2 m5 = new
       * Member2(&quot;ee&quot;, 30, 'f');
       * 
       * c1.getMember2().add(m1); c1.getMember2().add(m2); c1.getMember2().add(m3);
       * 
       * c2.getMember2().add(m4); c2.getMember2().add(m5);
       * 
       * HibernateUtil.getSession().save(c2); HibernateUtil.getSession().save(m4);
       * HibernateUtil.getSession().save(m5);
       * 
       * HibernateUtil.getSession().save(c1); HibernateUtil.getSession().save(m1);
       * HibernateUtil.getSession().save(m2); HibernateUtil.getSession().save(m3);
       */
      HibernateUtil.end(t1);
    }
  
  
    private static class HibernateUtil {
      private static SessionFactory factory;
      private static Session session;
      static {
        factory = new Configuration().configure().buildSessionFactory();
      }
  
      public static Session getSession() {
        return session;
      }
  
      public static Transaction begin() {
        session = factory.openSession();
        return session.beginTransaction();
      }
  
      public static void end(Transaction tran) {
        tran.commit();
      }
    }
  }
  </code></pre>