2

我正在使用 Spring 和 JPA 编写一个简单的应用程序。我有 2 个实体:用户和角色,关系为 N..1。

每当我尝试从数据库中获取这些实体中的任何一个时,都会出现异常(如下所示)。当一个实体试图通过其外键获取另一个实体时,将引发所述异常。

例如,当我要求一个角色时,它的所有属性都正确获取,除了 userCollection(分配给该角色的用户组)。

无论我使用哪种方法询问实体(.find(pk)、.createNamedQuery()、.createQuery()、...),总是会抛出异常。

以下是代码。我跳过了不相关的部分:

用户实体:



    @Entity
    @Table(name = "users")
    public class User implements Serializable {

        private static final long serialVersionUID = 1L;

        @Id
        @Basic(optional = false)
        @Size(min = 1, max = 50)
        private String id;

        @JoinColumn(name = "rol", referencedColumnName = "id")
        @ManyToOne(optional = false, fetch = FetchType.EAGER)
        private Role rol;

        ...

角色实体:



    @Entity
    @Table(name = "roles")
    public class Role implements Serializable {
        private static final long serialVersionUID = 1L;

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;

        @NotNull
        @Size(min = 1, max = 50)
        private String name;

        @OneToMany(cascade = CascadeType.ALL, mappedBy = "rol", fetch = FetchType.LAZY)
        private Collection userCollection;

        ...

尝试获取角色时抛出的异常:


    Exception [EclipseLink-6094] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.QueryException
    Exception Description: The parameter name [id] in the query's selection criteria does not match any parameter name defined in the query.
    Query: ReadAllQuery(name="userCollection" referenceClass=User sql="SELECT ID, EMAIL, NAME, rol FROM users WHERE (rol = ?)")
        at org.eclipse.persistence.exceptions.QueryException.parameterNameMismatch(QueryException.java:1031)
        at org.eclipse.persistence.internal.expressions.ParameterExpression.getValue(ParameterExpression.java:246)
        at org.eclipse.persistence.internal.databaseaccess.DatabaseCall.translate(DatabaseCall.java:918)
        at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:204)
        at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:191)
        at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeSelectCall(DatasourceCallQueryMechanism.java:262)
        at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.selectAllRows(DatasourceCallQueryMechanism.java:618)
        at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllRowsFromTable(ExpressionQueryMechanism.java:2537)
        at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllRows(ExpressionQueryMechanism.java:2496)
        at org.eclipse.persistence.queries.ReadAllQuery.executeObjectLevelReadQuery(ReadAllQuery.java:455)
        at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:997)
        at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:675)
        at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:958)
        at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:432)
        ...

我试图从角色实体中删除 userCollection。如果我尝试获得一个角色,它工作得很好,但是如果我尝试找到一个用户,我会得到以下异常:



    org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: Transaction marked for rollback.
        at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1014)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:755)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:724)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:475)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:270)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
        ...

我不知道如何解决这个问题。我花了很多时间。帮助将不胜感激:)

4

1 回答 1

0

首先,您没有指明您的桌子布局,这使得回答您的问题成为一种猜谜游戏。

首先,我会避免@BasicUser. @Size没关系,但你可能也想在 JPA 中匹配它。见下文(注解中的nullable=falseunique=true属性是多余的):@Id

@Id
@Column(length=50, nullable=false, unique=true)
@Size(min = 1, max = 50)
private String id;

如果 ID 基本上是用户名,那么这是一个坏主意。如果用户想要更改他的用户名,事情可能会变得棘手。此外,对表的外键引用users需要 50 个字节而不是 4 个(它比这更复杂,但你明白了)。我会添加一个常规IntegerID 和一个单独的userName字段。用户永远不需要查看 ID。

应给予类似处理Role.name

@Column(length=50, nullable=false, unique=true)
@Size(min = 1, max = 50)
private String name;

其次,看起来一个用户只能拥有一个角色?严重地?无论如何,如果是这种情况,referencedColumnName则不需要该属性,因为 ID 列roles使用默认名称:

@ManyToOne(optional = false, fetch = FetchType.EAGER)
@JoinColumn(name = "rol")
private Role rol;

将外键列命名为“rol”而不是“role_id”不是一个好主意。我会使用默认值(只是放下@JoinColumn东西)。

如果您希望用户可以拥有多个角色,则需要一个连接表(@JoinTable如果您想使用默认值,可以省略这些内容):

@ManyToMany
@JoinTable(
    name = "user_roles",
    joinColumns = { @JoinColumn(name = "user_id") },
    inverseJoinColumns = { @JoinColumn(name = "role_id") }
)
private List<Role> roles;

第三,很难看出拥有用户列表的用处Role。我会完全删除它。而是使用类似的东西user.getRoles.contains(SomeRole)来查看用户是否具有特定角色。

最后,查看您的代码,我应该澄清几件事:

  • 在“列”注释(@Column@JoinColumn等)中,namereferencedColumnName属性允许您指定实际的列名。它们不引用您的类中的字段名称。
于 2013-05-07T22:42:56.417 回答