title: JPA: join tables but after that still makes sequence of queries
body: <p>I'm sorry if that is too silly or not complete.<br/>
  I want to make one query, joining all tables at once.</p>
  
  <pre><code>@NamedQuery(name="User.findByLogin",
          query="SELECT u FROM User u " +
            "left outer join fetch u.userInfo ui " +
                "left outer join fetch u.freeEvents fe " +
                "left outer join fetch u.paidEvents pe " +
                "left outer join fetch fe.action fea " +
                "left outer join fetch pe.action pea " +
                "where u.login = :login")
  </code></pre>
  
  <p>and it works (no errors, no warnings, sql generated), and SQL is fine, and all appropriate data is retrieved in mysql console. But after that it makes many requests to find actions by id, and it looks like hibernate doesn't know that it had already fetched all needed data or have no idea what to do with it.<br/>
  All other similar joins with two tables are valid and work as expected.<br/>
  By the way, freeEvent and paidEvent are @Inheritance(strategy=InheritanceType.SINGLE_TABLE), they differs by "rate_type" column. I tried both eager and lazy fetch, and hibernate @Fetch annotation.<br/>
  The sql itself:</p>
  
  <pre><code>select * #---lots of fields here, all valid
    from Users user0_ left outer join UserInfos userinfo1_ on user0_.`user_info_id`=userinfo1_.id
              left outer join Events freeevents2_ on user0_.id=freeevents2_.`user_id` and freeevents2_.rate_type=1
              left outer join FreeActions freeaction4_ on freeevents2_.`action_id`=freeaction4_.`id`
              left outer join Events paidevents3_ on user0_.id=paidevents3_.`user_id` and paidevents3_.rate_type=2
              left outer join PaidActions paidaction5_ on paidevents3_.`action_id`=paidaction5_.`id` where user0_.`login`='testuser'
  </code></pre>
  
  <p>Question: where is the problem? Are my classes poorly annotated, or that is a normal hibernate behaviour, where to find a solution?</p>
  
  <p>Entities: (without getters, setters and fields that are not mapped by anyone)</p>
  
  <pre><code>@Entity
  @Table(name="Events")
  @PersistenceUnit(name="default")
  @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
  @DiscriminatorColumn(name="rate_type", discriminatorType=DiscriminatorType.INTEGER)
  public class AbstractEvent {
  
      @Id
      @GeneratedValue(strategy=GenerationType.IDENTITY)
      private Long Id;
  
      @ManyToOne(fetch=FetchType.LAZY)
      private models.User user;
  
      @Column(name="rate_type", insertable=false, updatable=false)
      private byte rateType;
  }
  
  @Entity
  @DiscriminatorValue(RateTypeHelper.RATE_TYPE_FREE) //it just a constant of type integer == 1
  @PersistenceUnit(name="default")
  public class FreeEvent extends models.events.AbstractEvent {
  
      @OneToOne(cascade=CascadeType.PERSIST, fetch=FetchType.LAZY)
      @JoinColumn(name="`action_id`")
      private FreeAction action;
  
      public FreeAction getAction() {
          return action;
      }
  
      public void setAction(FreeAction action) {
          this.action = action;
      }
  }
  
  @Entity
  @DiscriminatorValue(RateTypeHelper.RATE_TYPE_PAID)
  @PersistenceUnit(name="default")
  public class PaidEvent extends models.events.AbstractEvent {
  
      @OneToOne(cascade=CascadeType.PERSIST, fetch=FetchType.LAZY)
      @JoinColumn(name="`action_id`")
      private PaidAction action;
  
      public PaidAction getAction() {
          return action;
      }
  
      public void setAction(PaidAction action) {
          this.action = action;
      }
  }
  </code></pre>
  
  <p>Note: abstract action here is not used now. It doesn't have any fields or methods. Just empty class for futures needs.</p>
  
  <pre><code>@Entity
  @Table(name="FreeActions")
  @PersistenceUnit(name="default")
  @NamedQueries({
      @NamedQuery(name="FreeAction.findByUserId",
                  query="select a from FreeAction a " +
                        "left outer join fetch a.event e " +
                        "where e.user = :user_id")
  })
  public class FreeAction extends AbstractAction {
  
      @Id
      @GeneratedValue(strategy=GenerationType.IDENTITY)
      @Column(name="`id`")
      private Long Id;
  
      @OneToOne(mappedBy="action", fetch=FetchType.LAZY)
      private models.events.FreeEvent event;
  }
  
  @Entity
  @Table(name="PaidActions")
  @PersistenceUnit(name="default")
  @NamedQueries({
      @NamedQuery(name="PaidAction.findByUserId",
                  query="select a from PaidAction a " +
                        "left outer join fetch a.event e " +
                        "where e.user = :user_id")
  })
  
  public class PaidAction extends AbstractAction {    
      @Id
      @GeneratedValue(strategy=GenerationType.IDENTITY)
      @Column(name="`id`")
      private Long Id;
  
      @OneToOne(mappedBy="action", fetch=FetchType.LAZY)
      private models.events.PaidEvent event;
  }
  
  @Entity
  @Table(name="Users")
  @PersistenceUnit(name="default")
  @NamedQueries({
      @NamedQuery(name="findFullUserById",
                  query="select u from User u "+ 
                        "left outer join fetch u.userInfo ui " +
                        "where u.id = :id"),
      @NamedQuery(name="User.findByLoginPassword",
                  query="SELECT u FROM User u left outer join fetch u.userInfo ui " +
                        "where u.login = :login and u.password = :password"),
      @NamedQuery(name="User.findByLogin",
                  query="SELECT u FROM User u " +
                        "left outer join fetch u.userInfo ui " +
                        "left outer join fetch u.freeEvents fe " +
                        "left outer join fetch u.paidEvents pe " +
                        "left outer join fetch fe.action fea " +
                        "left outer join fetch pe.action pea " +
                        "where u.login = :login")
  })
  public class User {
  
      @Id
      @GeneratedValue(strategy = GenerationType.AUTO)
      @Column(name="id")
      private Long Id;
  
      @OneToMany(fetch=FetchType.LAZY)
      @JoinColumn(name="`user_id`")
      private Set&lt;FreeEvent&gt; freeEvents;
  
      @OneToMany(fetch=FetchType.LAZY)
      @JoinColumn(name="`user_id`")
      private Set&lt;PaidEvent&gt; paidEvents;
  
      @OneToOne(cascade=CascadeType.PERSIST, fetch=FetchType.LAZY)
      @JoinColumn(name="`user_info_id`")
      private UserInfo userInfo;
  }
  
  @Entity
  @Table(name="UserInfos")
  @PersistenceUnit(name="default")
  public class UserInfo {
  
      @Id
      @GeneratedValue(strategy = GenerationType.AUTO)
      @Column(name="id")
      private Long Id;
  
      @OneToOne(mappedBy="userInfo")
      private User user;
  }
  </code></pre>