2013-05-07 64 views
1

我正在使用Spring和JPA編寫一個簡單的應用程序。我有兩個實體:用戶和角色,關係爲N..1。JPA:獲取引用其他實體的異常

每當我嘗試從數據庫中獲取這些實體時,就會得到一個異常(如下所示)。當一個實體試圖通過其外鍵獲取另一個實體時引發異常。

例如,當我詢問角色時,除了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) 
     ... 

我不知道如何解決這個問題。我花了很多時間。幫助,將不勝感激:)

回答

0

首先,你不指出​​你的表格佈局,這使得回答你的問題猜謎遊戲。

首先,我會避免在User的ID列上使用@Basic@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個(這比這更復雜一點,但您明白了)。我會添加一個常規的Integer ID和一個單獨的userName字段。用戶從不需要查看ID。

類似的待遇應給予Role.name

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

其次,它看起來像一個用戶只能有一個角色?真的嗎?無論如何,如果這是不需要referencedColumnName屬性的情況下,因爲在roles ID列使用默認名稱:

@ManyToOne(optional = false, fetch = FetchType.EAGER) 
@JoinColumn(name = "rol") 
private Role 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屬性允許你指定實際的列名稱。他們不會在你的類中引用字段名稱。