У меня есть 2 объекта - Пользователь и Роль, которые имеют следующие отношения: Пользователь имеет многоточечное отношение к себе и многоточечное отношение с сущностью Роль.
@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;
...
}
и роль:
public class RoleEntity implements Serializable{
@Id
@Column(name = "Id", unique = true, nullable = false)
private String id;
...
}
Странная вещь в настройке БД заключается в том, что отношение User_User основано на двоичных ключах Id.
create table if not exists User_User (
UserParent binary,
UserChild binary
);
а роль пользователя основана на varchars
create table if not exists KNUser_UserRole (
UserLogin varchar,
RoleId varchar,
);
Теперь, когда он работает, отношения между пользователями работают хорошо. Однако, когда я пытаюсь получить доступ к коллекции, возвращаемой для ролей, я получаю 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)
Похоже, что UserEntity преобразуется в какую-то двоичную (?) вещь. Однако первое отношение между самими пользователями работает нормально, а отношение с другой таблицей — неправильно.
Я использую разные столбцы разных типов для объединения таблиц. Разрешено ли это делать таким образом?
Еще одна странность заключается в том, что когда я переключаю аннотацию @Id на поле login, роли работают нормально, без проблем, но затем, конечно, PersistentBag самоподключается key — это логин, а не идентификатор, что разрывает связь, и результаты не извлекаются. Но преобразование из UserEntity в "[B" не выполняется.
Кроме того, если я оставлю все как в примере и изменю тип Id на String (и БД на varchar), он также начнет работать (конечно, не согласуется с таблицей User_User).
Что я делаю неправильно? В чем причина получения исключения classcastException в этом случае? Почему это работает, когда я меняю byte[] на String? Пожалуйста, дайте мне знать, если у вас есть идеи. Я не хочу менять дизайн БД, потому что это приведет к большому количеству проблем с миграцией и совместимостью для клиентов, уже использующих БД.
Просто примечание: @Id должен быть в двоичном поле Id, иначе я не смогу выполнить самосоединение (я не смог дважды указать столбец, не являющийся первичным ключом, см.: Возможно ли самосоединение Hibernate ManyToMany для неключевых столбцов ? получение MappingException).
Привет Адам