有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么@ManyToMany不能处理非主键列?

我有两个实体-用户和角色,它们具有以下关系:用户与自身有多个关系,与角色实体有多个关系

@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;

    ...
}

DB设置的奇怪之处在于,用户与用户的关系是基于二进制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)

看起来用户实体正在转换为某个二进制(?)事情但是,用户之间的第一个关系可以正常工作,但是与另一个表的关系是错误的

我使用不同类型的不同列来连接表。允许这样做吗

另一件奇怪的事情是,当我将@Id注释切换到login字段时,角色工作正常,没有问题,但是当然,self-join-PersistentBag键是login而不是Id,这打破了关系,并且没有检索到结果。但是从UserEntity到“[B”的转换没有完成

同样,如果我将事情保留在示例中,并将Id类型更改为String(DB更改为varchar),它也会开始工作(当然,与User\u User表不一致)

我做错了什么?在这种情况下获取classcastexception的原因是什么?当我将byte[]更改为String时,它为什么工作?如果你有任何想法,请告诉我。我不想改变数据库的设计,因为这将导致大量的迁移和兼容性问题的客户端已经使用数据库

请注意:@Id必须位于Id二进制字段上,否则我将无法进行自连接(我无法两次指向不是主键的列,请参见:Is Hibernate ManyToMany self-join possible for non-key columns? getting mappingException

干杯 亚当


共 (1) 个答案

  1. # 1 楼答案

    联接表中引用的列必须是唯一的条目,在这里,如果您在登录字段中放置@Id,则它可以正常工作,但当您将其更改为除@Id列以外的其他列时,您无法确定这些条目是否唯一。你能做的是

        @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; 
    

    我认为应该行得通