title: Why is @ManyToMany not working with non-primary key columns?
body: <p>I have 2 entities - User and Role which have following relations: User has a manytomany relation to itself and a manytomany relation with the Role entity.</p>
  
  <pre><code>@Entity
  public class UserEntity implements Serializable {
  
      @Id
      @Column(length = 12, columnDefinition = "BINARY(12)", name = "Id", unique = true)
      private byte[] id;
  
      @Column(name = "Login", unique = true, nullable = false)
      private String login;
  
      @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
      @JoinTable(name = "User_Role",
      joinColumns = { @JoinColumn(name = "UserLogin", referencedColumnName = "Login") },
      inverseJoinColumns = { @JoinColumn(name = "RoleId", referencedColumnName = "Id") })
      private Set&lt;RoleEntity&gt; roles;
  
      @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
      @JoinTable(name = "User_User",
      joinColumns = { @JoinColumn(name = "UserParent") },
      inverseJoinColumns = { @JoinColumn(name = "UserChild") })
      private Collection&lt;UserEntity&gt; children;
  
  ...
  }
  </code></pre>
  
  <p>and Role:</p>
  
  <pre><code>public class RoleEntity implements Serializable{
  
      @Id
      @Column(name = "Id", unique = true, nullable = false)
      private String id;
  
      ...
  }
  </code></pre>
  
  <p>The strange thing about the setup of DB is that the User_User relation is based on the binary Id keys</p>
  
  <pre><code>create table if not exists User_User (
      UserParent binary,
      UserChild binary
  );
  </code></pre>
  
  <p>and the user-role is based on varchars</p>
  
  <pre><code>create table if not exists KNUser_UserRole (
      UserLogin varchar, 
      RoleId varchar,
  );
  </code></pre>
  
  <p>Now, when it runs, the user-user relationship work well. However, when I try to access the collection returned for roles, I get a ClassCastException:</p>
  
  <pre><code>java.lang.ClassCastException: **.entity.UserEntity cannot be cast to [B
      at org.hibernate.type.descriptor.java.PrimitiveByteArrayTypeDescriptor.extractHashCode(PrimitiveByteArrayTypeDescriptor.java:41)
      at org.hibernate.type.AbstractStandardBasicType.getHashCode(AbstractStandardBasicType.java:201)
      at org.hibernate.type.AbstractStandardBasicType.getHashCode(AbstractStandardBasicType.java:205)
      at org.hibernate.engine.spi.EntityKey.generateHashCode(EntityKey.java:114)
      at org.hibernate.engine.spi.EntityKey.&lt;init&gt;(EntityKey.java:79)
      at org.hibernate.internal.AbstractSessionImpl.generateEntityKey(AbstractSessionImpl.java:240)
      at org.hibernate.engine.internal.StatefulPersistenceContext.getCollectionOwner(StatefulPersistenceContext.java:740)
      at org.hibernate.loader.Loader.readCollectionElement(Loader.java:1181)
      at org.hibernate.loader.Loader.readCollectionElements(Loader.java:800)
      at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:651)
      at org.hibernate.loader.Loader.doQuery(Loader.java:856)
      at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:289)
      at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
      at org.hibernate.loader.Loader.loadCollection(Loader.java:2175)
      at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:61)
      at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:622)
      at org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:82)
      at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1606)
      at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:379)
      at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:112)
      at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:180)
  </code></pre>
  
  <p>It looks like the UserEntity is being cast to some binary(?) thing. However, the first relation between users themselves works fine, but the one with another table is wrong.</p>
  
  <p>I am using different columns of different types to join tables. Is it allowed to do it this way?</p>
  
  <p>Another strange thing is that when I switch the @Id annotation to be on the <strong><em>login</em></strong> field, the roles work fine, no issue, but then of course the self-join PersistentBag key is the Login instead of Id, which breaks the relation and no results are retrieved. But the conversion from UserEntity to the "[B" is not done. </p>
  
  <p>Also if I leave things as in example and change the Id type to String (and the DB to varchar) it also starts working (of course not consistently with the User_User table).</p>
  
  <p>What am I doing wrong? What is the reason for getting the classcastexception in this case? Why it work when I change the byte[] to String? Please let me know if you have any ideas. I do not want to change the DB design cause this would lead to lots migration and compatibility issues for clients already using the DB.</p>
  
  <p>Just a note: the @Id has to be on the Id binary field as otherwise I wouldn't be able to make a self-join (I was unable to point twice to a column not being a primary key see: <a href="https://stackoverflow.com/questions/25660565/is-hibernate-manytomany-self-join-possible-for-non-key-columns-getting-mappinge">Is Hibernate ManyToMany self-join possible for non-key columns? getting mappingException</a>). </p>
  
  <p>Cheers
  Adam</p>