I have three entities: Account, AccountAttribut and Attribut. Account and Attribut are associated via AccountAttribut in a many-to-many relationship like it is described [1].
The question is: Why cant i use: "aa_pk.attribut" as a property name to navigate through the association tree? Because this is the property name, i defined in my AccountAttribut entity, isnt it?
Can you help me with this issue?
[1]: http://giannigar.wordpress.com/2009/09/04/mapping-a-many-to-many-join-table-with-extra-column-using-jpa/ "Mapping a many-to-many join table with extra column using JPA"
These are relevant code extracts:
Account:
Code:
@Entity
@Table(name = "account")
public class Account {
private Long accountId;
private List<AccountAttribut> accountAttributes = new LinkedList<AccountAttribut>();
private Person person;
private Zielsystem zielsystem;
public Account() {
}
// ...
}
AccountAttribut:
Code:
@Entity
@Table(name="account_attribut")
@AssociationOverrides({
@AssociationOverride(name="aa_pk.account", joinColumns = @JoinColumn(name="account_id")),
@AssociationOverride(name="aa_pk.attribut", joinColumns = @JoinColumn(name="attribut_id"))
})
public class AccountAttribut {}
private AccountAttributPk aa_pk = new AccountAttributPk();
@Column(name="wert")
private String wert;
@EmbeddedId
public AccountAttributPk getAa_pk() {
return aa_pk;
}
public void setAa_pk(AccountAttributPk aa_pk) {
this.aa_pk = aa_pk;
}
@Transient
public Account getAccount() {
return getAa_pk().getAccount();
}
public void setAccount(Account account) {
getAa_pk().setAccount(account);
}
@Transient
public Attribut getAttribut() {
return getAa_pk().getAttribut();
}
public void setAttribut(Attribut attribut) {
getAa_pk().setAttribut(attribut);
}
public String getWert() {
return wert;
}
public void setWert(String wert) {
this.wert = wert;
}
public boolean equals(Object o) {
if (this== o) return true;
if (o ==null|| getClass() != o.getClass()) return false;
AccountAttribut that = (AccountAttribut) o;
if (getAa_pk() !=null?!getAa_pk().equals(that.getAa_pk()) : that.getAa_pk() !=null) return false;
return true;
}
public int hashCode() {
return (getAa_pk() !=null? getAa_pk().hashCode() : 0);
}
}
AccountAttributPk:
Code:
public class AccountAttributPk implements Serializable {
private static final long serialVersionUID = -1551814445010872872L;
private Account account;
private Attribut attribut;
@ManyToOne
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
@ManyToOne
public Attribut getAttribut() {
return attribut;
}
public void setAttribut(Attribut attribut) {
this.attribut = attribut;
}
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
AccountAttributPk that = (AccountAttributPk) o;
if (account != null ? !account.equals(that.account) : that.account != null)
return false;
if (attribut != null ? !attribut.equals(that.attribut)
: that.attribut != null)
return false;
return true;
}
public int hashCode() {
int result;
result = (account != null ? account.hashCode() : 0);
result = 31 * result + (attribut != null ? attribut.hashCode() : 0);
return result;
}
}
The CriteriaQuery:
Code:
List<Account> queried_accounts = HibernateUtils.criteriaList(
session.createCriteria(Account.class).
createCriteria("accountAttribute").
createCriteria("aa_pk.attribut").
add(Restrictions.isNotNull("name"))
);
The Exception:
org.hibernate.exception.SQLGrammarException: could not extract ResultSet
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:80)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
I tried the following solutions from a proposed solution in Stackoverflow:
(Solution 1)
Code:
List<Account> queried_accounts = HibernateUtils.criteriaList(
session.createCriteria(Account.class).
createCriteria("accountAttributes","accAttrAlias").
createCriteria("accAttrAlias.aa_pk","accAttrAAPKAlias").
createCriteria("accAttrAAPKAlias.attribut", "attrAlias").
add(Restrictions.isNotNull("attrAlias.name"))
);
Java Errorlog:
org.hibernate.QueryException: Criteria objects cannot be created directly on components. Create a criteria on owning entity and use a dotted property to access component property: accountAttributes.aa_pk
(Solution 2)
Code:
List<Account> queried_accounts = HibernateUtils.criteriaList(
session.createCriteria(Account.class).
createCriteria("accountAttributes","accAttrAlias").
createCriteria("accAttrAlias.aa_pk.attribut", "attrAlias").
add(Restrictions.isNotNull("attrAlias.name"))
);
Java Errorlog:
org.hibernate.exception.SQLGrammarException: could not extract ResultSet
Hibernate Errorlog:
"Hibernate: select this_.account_id as account_1_3_4_, this_.person_id as person_i2_3_4_, this_.zielsystem_id as zielsyst3_3_4_, accattrali1_.account_id as account_3_4_0_, accattrali1_.attribut_id as attribut2_4_0_, accattrali1_.wert as wert1_4_0_, person5_.person_id as person_i1_2_1_, personenat6_.person_id as person_i3_2_6_, personenat6_.attribut_id as attribut2_8_6_, personenat6_.person_id as person_i3_8_6_, personenat6_.attribut_id as attribut2_8_2_, personenat6_.person_id as person_i3_8_2_, personenat6_.wert as wert1_8_2_, zielsystem7_.zielsystem_id as zielsyst1_9_3_, zielsystem7_.name as name2_9_3_ from account this_ inner join account_attribut accattrali1_ on this_.account_id=accattrali1_.account_id left outer join PERSON person5_ on this_.person_id=person5_.person_id left outer join person_attribut personenat6_ on person5_.person_id=personenat6_.person_id left outer join zielsystem zielsystem7_ on this_.zielsystem_id=zielsystem7_.zielsystem_id where attralias2_.name is not null
Feb 20, 2014 11:25:11 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 1054, SQLState: 42S22
Feb 20, 2014 11:25:11 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: Unknown column 'attralias2_.name' in 'where clause'"