Après pas mal de recherche, j’ai trouvé une solution à une difficulté récurrente :

  • Une méthode X ajoute un critère sur une des tables d’un "join" (exemple order.product.price>0)
  • Une méthode Y ajoute un autre critère sur la même table du "join" (exemple order.product.deleted=false)

Hibernate renvoie une erreur de type QueryException en disant « duplicate association path : product…. » Et nous n’arrivions pas à accéder au premier critère posé par la méthode Y.

C’est finalement une histoire de cast : l’interface criteria n’expose pas la méthode iterateSubCriteria, son implémentation CriteriaImpl, si :

Iterator<Subcriteria> iter = ((CriteriaImpl)crit).iterateSubcriteria();
boolean found = false;
while ( iter.hasNext() ) {
	Subcriteria subcriteria = iter.next();
	if ("product".equalsIgnoreCase(subcriteria.getPath())) {
		subcriteria.add(Expression.eq("deleted", false));
		found=true;
		break;
	}
}
if(!found){
	crit.createCriteria("product").add(Expression.eq("deleted", false));
}