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.
@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<RoleEntity> roles;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name = "User_User",
joinColumns = { @JoinColumn(name = "UserParent") },
inverseJoinColumns = { @JoinColumn(name = "UserChild") })
private Collection<UserEntity> children;
...
}
and Role:
public class RoleEntity implements Serializable{
@Id
@Column(name = "Id", unique = true, nullable = false)
private String id;
...
}
The strange thing about the setup of DB is that the User_User relation is based on the binary Id keys
create table if not exists User_User (
UserParent binary,
UserChild binary
);
and the user-role is based on varchars
create table if not exists KNUser_UserRole (
UserLogin varchar,
RoleId varchar,
);
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:
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.<init>(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)
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.
I am using different columns of different types to join tables. Is it allowed to do it this way?
Another strange thing is that when I switch the @Id annotation to be on the login 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.
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).
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.
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: Is Hibernate ManyToMany self-join possible for non-key columns? getting mappingException ).
Cheers Adam
the referred column in your join table must be unique entry, here if you put @Id on login field then it works fine,but when you change it to different other than @Id column you cant be sure about the entries will be unique.what you can do is,
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(name = "User_Role",
joinColumns = { @JoinColumn(name = "UserLogin", referencedColumnName = "Id") },
inverseJoinColumns = { @JoinColumn(name = "RoleId", referencedColumnName = "Id") })
private Set<RoleEntity> roles;
I think it should work.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.