title: Map two classes to one table using JPA to speed up spring security UserDetailsService
body: <p>I want to make a secured restful service using Spring, JPA and Hibernate.</p>
  
  <p>Each endpoint must be secured and I use spring security for that purpose using a specific UserDetailsService as describe in the spring security documentation : 
  <a href="http://docs.spring.io/spring-security/site/docs/3.2.4.RELEASE/reference/htmlsingle/#userdetailsservice-implementations" rel="nofollow noreferrer">http://docs.spring.io/spring-security/site/docs/3.2.4.RELEASE/reference/htmlsingle/#userdetailsservice-implementations</a></p>
  
  <p>Here the point : as each request will be authentified, it means that for each request, my UserDetailsService will load a user form my database and need to get its password and its roles. </p>
  
  <p>The default JdbcDaoImpl use 2 requests to find a user and its roles. 
  I don't use it because :</p>
  
  <ul>
  <li>I want to have my users' Id in a UserDetails object as my business controller use it.</li>
  <li>I want that my users are loaded with only one request</li>
  </ul>
  
  <p>My user business object look like :</p>
  
  <pre><code>@Entity
  @Inheritance(strategy = InheritanceType.JOINED)
  @Table(name = "aa_user")
  public class User
  {
     @Id
     @GeneratedValue(strategy = GenerationType.AUTO)
     Long id;
  
     @NotNull
     @Column(unique = true)
     protected String login;
  
     protected String password;
  
     @ManyToMany(targetEntity = Role.class)
     protected List&lt;Role&gt; roles;
  
     //getter/setter
  }
  </code></pre>
  
  <p>And my repository :</p>
  
  <pre><code>public interface UserRepository extends JpaRepository&lt;User, Long&gt;
  {
      @Query("SELECT u FROM User u JOIN FETCH u.roles where u.login = :login")
      User findByLogin(@Param("login") String login);
  }
  </code></pre>
  
  <p>My UserDetailsService :</p>
  
  <pre><code>@Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
  {
      User user = null;
      try
      {
          user = userRepository.findByLogin(username);
      } catch (Throwable e) {
          e.printStackTrace();
          throw new UsernameNotFoundException("Can't find username: " + username);
      }
      if (user == null) {
          throw new UsernameNotFoundException("Can't find username: " + username);
      }
  
      UserDetailsImpl userDetails = new UserDetailsImpl(user);
  
      return userDetails;
  } 
  </code></pre>
  
  <p>I have a lot of User subclasses (like Seller, ...) which have associations to other objects fetch eagerly for business purpose and with this implementation, the <code>userRepository.findByLogin(username)</code> make something like 3 or more heavy joins to give me the right full fetch user object (which is "normal" of course), but I only want one light query with only the User's field initialized.  </p>
  
  <p>According to this question : 
  <a href="https://stackoverflow.com/questions/16541129/avoiding-outer-joins-across-tables-when-using-joined-inheritance-with-spring-dat">Avoiding outer joins across tables when using joined inheritance with Spring Data JPA</a> what I want to do seems complicated, but I found that I could use <code>@Polymorphism</code> Hibernate annotation with <code>PolymorphismType.EXPLICIT</code> : 
  <a href="https://stackoverflow.com/a/18358863/1661338">https://stackoverflow.com/a/18358863/1661338</a></p>
  
  <p><code>@Polymorphism</code> is not JPA compliant and brake parts of my business logic or need that I refactor a lot of query.</p>
  
  <p>To avoid that, I add a second class mapped on the same Table :</p>
  
  <pre><code>@Entity
  @Table(name = "aa_user")
  public class LightUser implements SimpleUser
  {  
     @Id
     @GeneratedValue(strategy = GenerationType.AUTO)
     Long id;
  
     @NotNull
     @Column(unique = true)
     protected String login;
  
     protected String password;
  
     @ManyToMany(targetEntity = Role.class)
     protected List&lt;Role&gt; roles;
  
     //getter
  }
  </code></pre>
  
  <p>And my repository :</p>
  
  <pre><code>public interface LightUserRepository extends JpaRepository&lt;User, Long&gt;
  {
      @Query("SELECT u FROM LightUser u JOIN FETCH u.roles where u.login = :login")
      LightUser findByLogin(@Param("login") String login);
  }
  </code></pre>
  
  <p>Both <code>User</code>and <code>LightUser</code> implements the same <code>SimpleUser</code> interface with all getter needed for my <code>UserDetailsImpl</code>.</p>
  
  <p>Now, <code>lightUserRepository.findByLogin(username)</code> make the smartest query possible and get only what I want.</p>
  
  <p>I still have questions :</p>
  
  <ul>
  <li>Is it JPA compliant ?</li>
  <li><code>hbm2ddl.SchemaExport</code> work but try to put 2 times the same foreign key between table <code>aa_user</code> and role table. How to avoid that ?</li>
  <li>It could be less painful to write if I can make a query with the same behavior as <code>PolymorphismType.EXPLICIT</code>. Does anyone know if it's possible ?</li>
  <li>Can LightUser be "readOnly" object to avoid mistakes ?</li>
  </ul>