0

Currently I am trying to use hibernate (version 4.3.Final) to retrieve an object with a composite primary key containing another hibernate bean association. The criteria I am using is as follows:

session.createCriteria(IdentityIdentifierHibernateBean.class)
       .setFetchMode("key.type", FetchMode.JOIN);   
       .createAlias("key.type","typeAlias",JoinType.INNER_JOIN);
       .add(Restrictions.and(
                Restrictions.eq("key.value", "value"),
                Restrictions.eq("typeAlias.id", "id value")))
       .list();

When I run this I get an error of:

1. SQL Error: 0, SQLState: 42P01
2. missing FROM-clause entry for table "typealias1_"

Which the reason is apparent when I view the generated sql as shown below:

select 
     this_.type as type4_4_0_, 
     this_.value as value1_4_0_, 
     this_.id as id2_4_0_, this_.scope as scope3_4_0_ 
from 
     identityIdentifier this_ 
where 
    (this_.value=? and typealias1_.id=?)

When running createAlias (or createCritera) isn't hibernate suppose to generate a join statement? I have tried both methods and tried creating aliases for the composite primary key as well. Either way, neither of these methods works as a join statement is never created. Is this a bug with resolving nested hibernate beans referenced in an embedded composite primary key? Or am I missing something....

For reference here's a simplified version of the hibernate classes (hashCode, equals and setters not included):

@Entity
@Table(name = "identityIdentifier")
public class IdentityIdentifierHibernateBean implements Serializable {  
    private IdentityIdentifierPrimaryKey key;

    @EmbeddedId
    public IdentityIdentifierPrimaryKey getKey() {
        return key;
    }
}

@Embeddable
public class IdentityIdentifierPrimaryKey implements Serializable {
    private String value;
    private IdentityIdentifierTypeHibernateBean type;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "type", referencedColumnName="id",  unique = true, nullable = false)
    public IdentityIdentifierTypeHibernateBean getType() {
        return type;
    }

    @Column(name = "value", unique = false, nullable = false, length = 255)
    public String getValue() {
        return value;
    }
}

@Entity
@Table(name = "identityIdentifierType")
public class IdentityIdentifierTypeHibernateBean implements Serializable {
    private String id;

    @Id
    @Column(name = "id", unique = true, nullable = false, length=38)
    public String getId() {
        return id;
    }
}
dsutherland
  • 792
  • 6
  • 15

2 Answers2

0

After countless hours of trying to get the criteria API to work (which I genuinely believe is broken for composite keys at this point) I decided to switch to using HQL query instead. After about 20 minutes, I was easily able to get a working query. Word for the wise, don't use composite keys and the criteria api in combination.

Query query=session.createQuery(
            "select distinct identity from IdentityIdentifierHibernateBean as identity "
            + "inner join identity.key.type as type "
            + "where (identity.key.value=:value and type.id=:typeid)")
            .setParameter("value", type.getIdentityIdentifierValue())
            .setParameter("typeid", type.getTypeOfIdentityIdentifier());

beanList = (List<IdentityIdentifierHibernateBean>) query.list();
dsutherland
  • 792
  • 6
  • 15
0

I've run into the same problem as you and was able to solve it after a lot of searching by refactoring the composite id. I've removed the hibernate entities from the composite id and moved them to the the entity itself. The foreign keys are mapped my using the @MapsId(JPA 2.0) annotation and keys for entity table by @AttributeOverride.

http://www.objectdb.com/api/java/jpa/MapsId
http://www.objectdb.com/api/java/jpa/AttributeOverride