2014-11-07 2 views
0

У меня проблема с запросом при использовании объектов с двунаправленными ассоциациями.Карта отображения Hibernate с двунаправленной ассоциацией @OneToMany

У меня есть сущность Кошелька, который имеет некоторые отношения к двум другим объектам. Существует проблема с отношением к сущности WalletBranchOffice. Если я прокомментирую эту часть кода, все будет хорошо. Вот мои объекты:

Wallet.java

@Entity 
@Table(name="WALLET", schema=SchemasConfig.SCHEMA_NEW) 
@Cacheable(true) 
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY) 
public class Wallet implements Serializable { 

private static final long serialVersionUID = 3307006915060155334L; 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
@Column(name="WALLET_ID") 
private Integer walletId; 
public Integer getWalletId() { 
    return walletId; 
} 

@Column(name="INTERNAL_REFERENCE", nullable=false, length=32) 
private String internalReference; 
public String getInternalReference() { 
    return internalReference; 
} 

@ManyToOne(fetch=FetchType.EAGER) 
@JoinColumn(name="CURRENCY_ID", nullable=false) 
private Currency currency; 
public Currency getCurrency() { 
    return currency; 
} 

@Column(name = "CACHE_AMOUNT_SUM", nullable = false, precision = 13, scale = 2) 
private BigDecimal cacheAmountSum; 
public BigDecimal getCacheAmountSum() { 
    return cacheAmountSum; 
} 

@OneToMany(mappedBy="wallet", fetch=FetchType.EAGER) 
@MapKeyColumn(name="BRANCH_OFFICE_ID") 
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY) 
private Map<Integer, WalletBranchOffice> walletBranchOffices; 
public Map<Integer, WalletBranchOffice> getWalletBranchOffices() { 
    return walletBranchOffices; 
} 

@OneToMany(mappedBy="wallet", fetch=FetchType.EAGER) 
@MapKeyColumn(name="WALLET_PREV_ID") 
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY) 
/* 
* wallets which must be used before current wallet 
*/ 
private Map<Integer, WalletDependency> walletDependencies; 
public Map<Integer, WalletDependency> getWalletDependencies() { 
    return walletDependencies; 
} 

@OneToMany(mappedBy="walletPrev", fetch=FetchType.EAGER) 
@MapKeyColumn(name="WALLET_ID") 
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY) 
/* 
* wallets that can be used after current wallet 
*/ 
private Map<Integer, WalletDependency> dependentWallets; 
public Map<Integer, WalletDependency> getDependentWallets() { 
    return dependentWallets; 
} 

@Column(name = "TEXT_KEY") 
private String textKey; 
public String getTextKey() { 
    return textKey; 
} 

@Override 
public int hashCode() { 
    final int prime = 31; 
    int result = 1; 
    result = prime * result 
      + ((walletId == null) ? 0 : walletId.hashCode()); 
    return result; 
} 

@Override 
public boolean equals(Object obj) { 
    if (this == obj) 
     return true; 
    if (obj == null) 
     return false; 
    if (getClass() != obj.getClass()) 
     return false; 
    Wallet other = (Wallet) obj; 
    if (walletId == null) { 
     if (other.walletId != null) 
      return false; 
    } else if (!walletId.equals(other.walletId)) 
     return false; 
    return true; 
} 
} 

WalletBranchOffice.java

@Entity 
@Table(name="WALLET_BRANCH_OFFICE", schema=SchemasConfig.SCHEMA_NEW) 
@Cacheable 
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY) 
@Immutable 
public class WalletBranchOffice implements Serializable { 

private static final long serialVersionUID = 9135909966091486878L; 

@Id 
@Column(name="WALLET_BRANCH_OFFICE_ID") 
private Integer walletBranchOfficeId; 
public Integer getWalletBranchOfficeId() { 
    return walletBranchOfficeId; 
} 

@ManyToOne(fetch=FetchType.EAGER) 
@JoinColumn(name="WALLET_ID", nullable=false) 
private Wallet wallet; 
public Wallet getWallet() { 
    return wallet; 
} 


@ManyToOne(fetch=FetchType.EAGER) 
@JoinColumn(name="BRANCH_OFFICE_ID", nullable=false) 
private BranchOffice branchOffice; 
public BranchOffice getBranchOffice() { 
    return branchOffice; 
} 

@Column(name="CREATE DATETIME") 
@Type(type="com.uniqagroup.ims.common.EETDateType$TimestampType") 
private Timestamp createDatetime; 
public Timestamp getCreateDatetime() { 
    return createDatetime; 
} 
} 

Вот WalletDependency.java, с которой нет никаких проблем.

@Entity 
@Table(name="WALLET_DEPENDENCY",schema=SchemasConfig.SCHEMA_NEW) 
@Cacheable 
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY) 
@Immutable 
public class WalletDependency implements Serializable { 

private static final long serialVersionUID = -6665047739101469610L; 

@Id 
@Column(name="WALLET_DEPENDENCY_ID") 
private Integer walletRequiredId; 
public Integer getWalletRequiredId() { 
    return walletRequiredId; 
} 

@ManyToOne(fetch=FetchType.EAGER) 
@JoinColumn(name="WALLET_ID", nullable=false) 
private Wallet wallet; 
public Wallet getWallet() { 
    return wallet; 
} 

@ManyToOne(fetch=FetchType.EAGER) 
@JoinColumn(name="WALLET_PREV_ID",nullable=false) 
private Wallet walletPrev; 
public Wallet getWalletPrev() { 
    return walletPrev; 
} 
} 

И моя проблема заключается в том, что если я выполняю даже простой запрос на выборку, как:

List<Wallet> wallets = em.createQuery("FROM Wallet AS w",Wallet.class).getResultList(); 

с EntityManager, я получаю ошибку синтаксиса SQL:

Caused by: java.sql.SQLSyntaxErrorException: [SQL0199] Keyword AS not expected. Valid tokens: , FROM INTO. 
at com.ibm.as400.access.JDError.createSQLExceptionSubClass(JDError.java:852) [jt400-7.9_jdbc4.0.jar:JTOpen 7.9] 
at com.ibm.as400.access.JDError.throwSQLException(JDError.java:692) [jt400-7.9_jdbc4.0.jar:JTOpen 7.9] 
at com.ibm.as400.access.JDError.throwSQLException(JDError.java:662) [jt400-7.9_jdbc4.0.jar:JTOpen 7.9] 
at com.ibm.as400.access.AS400JDBCStatement.commonPrepare(AS400JDBCStatement.java:1763) [jt400-7.9_jdbc4.0.jar:JTOpen 7.9] 
at com.ibm.as400.access.AS400JDBCPreparedStatement.<init>(AS400JDBCPreparedStatement.java:354) [jt400-7.9_jdbc4.0.jar:JTOpen 7.9] 
at com.ibm.as400.access.AS400JDBCConnection.prepareStatement(AS400JDBCConnection.java:2166) [jt400-7.9_jdbc4.0.jar:JTOpen 7.9] 
at com.ibm.as400.access.AS400JDBCConnection.prepareStatement(AS400JDBCConnection.java:2108) [jt400-7.9_jdbc4.0.jar:JTOpen 7.9] 
at org.jboss.jca.adapters.jdbc.BaseWrapperManagedConnection.doPrepareStatement(BaseWrapperManagedConnection.java:732) 
at org.jboss.jca.adapters.jdbc.BaseWrapperManagedConnection.prepareStatement(BaseWrapperManagedConnection.java:707) 
at org.jboss.jca.adapters.jdbc.WrappedConnection.prepareStatement(WrappedConnection.java:404) 
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:161) [hibernate-core-4.2.0.Final-redhat-1.jar:4.2.0.Final-redhat-1] 
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:182) [hibernate-core-4.2.0.Final-redhat-1.jar:4.2.0.Final-redhat-1] 
... 163 more 
+0

Можете ли вы распечатать SQL, сгенерированный в обоих случаях, когда он работает и когда он не работает? Работает ли SQL, если выполняется непосредственно в вашей базе данных? –

+0

Благодарим вас за воспроизведение! После распечатки сгенерированного SQL я нашел проблему. Это всего лишь глупая техническая ошибка. Отсутствует знак «_» в сопоставлении свойства createDatetime для столбца create_datetime в объекте WalletBranchOffice. @Column (name = "CREATE DATETIME") @Type (type = "com.uniqagroup.ims.common.EETDateType $ TimestampType") приватная временная метка createDatetime; public Timestamp getCreateDatetime() { return createDatetime; } – RennyK

ответ

0

Благодарим Вас за повторы !!! После распечатки сгенерированного SQL я нашел проблему. Это всего лишь глупая техническая ошибка. Отсутствует знак «_» в сопоставлении свойства createDatetime для столбца create_datetime в объекте WalletBranchOffice. @Column (name = "CREATE DATETIME")

0

Нет необходимости для AS:

List<Wallet> wallets = em.createQuery("FROM Wallet w",Wallet.class).getResultList(); 

Некоторые примеры:

http://docs.oracle.com/javaee/6/tutorial/doc/bnbrg.html

+0

Нет, это не повод для ошибки. В JPQL ключевое слово AS необязательно. Даже без AS в запросе я получаю ту же ошибку. – RennyK