Over time, Hibernate classes can get very large – especially when modelling a complicated object (for example a financial transaction).
At this point, the @Embedded annotation comes to the rescue. The class annotated with @Embedded will be linked into the parent class as if it were one large class.
This even works with collections – the collection can be defined in the child (@Embeddable) class.
@Entity
public class PretendClass {
@Id
private Long transactionId;
@Embedded
private PretendChildClass pretendChildClass = new PretendChildClass();
}
@Embeddable
public class PretendChildClass {
@OneToMany(mappedBy = "transaction", targetEntity = TransactionAttributeImpl.class, cascade = CascadeType.ALL)
@MapKey(name = "transactionAttributeType")
@Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
private Map<TransactionAttributeType, TransactionAttribute> transactionAttributeMap = new HashMap<TransactionAttributeType, TransactionAttribute>();
}
One caveat – we ought to be programming to interfaces rather than implementations. Assuming we marked an interface as @Embedded, Hibernate will scan the interface and not import any of the fields defined in the class. In this case, one simply adds the @Target annotation:
@Embedded @Target(value = PretendChildClassImpl.class) private PretendChildClass pretendChildClass = new PretendChildClassImpl();
If using Criteria, this extra ‘level’ in the class hierarchy is simply referenced via a full-stop:
List<Transaction> transactionList;
Criteria crit = getHibernateTemplate().getSessionFactory().getCurrentSession().createCriteria(TransactionImpl.class);
crit.createAlias("embeddable_child_class.variable_we_want", "transactionExtRef"); // THE IMPORTANT LINE
crit.add(Restrictions.eq("transactionExtRef.transactionExtRefType", transactionExtRefType))
.add(Restrictions.eq("transactionExtRef.transactionExtRefValue", transactionExtRefValue));
transactionList = crit.list();
return transactionList;