Como fazer o criteria "montar" objetos corretamente?

Pessoal, preciso de ajuda para resolver um probleminha

Cada duplicata tem um historico de lancamento contabil e de negativacoes que preciso carregar de inicio (necessidade do cliente).
Quando executo a pesquisa abaixo o hibernate me retorno 60 duplicatas, porem so existem 12. Isso ocorre porque ele nao consegue “montar” o objeto por completo, dai ficam duplicatas com o mesmo id variando os lancamentos e historicos.

Eu preciso montar as 12 duplicatas corretas para somar o valor total, com 60 duplicatas tem dado um valor muito superior ao valor real.
Como eu posso usar o criteria de forma a conseguir montar os 12 objetos unindo as collections q ele possuem

@Entity
@Table(name="duplicata")
public class DuplicataBean {

	@Id @GeneratedValue(strategy=GenerationType.AUTO)
	@Column(name="DPLCT_ID")
	private Integer id;
	
	@ManyToOne
	@JoinColumn(name="CDNT_ID",insertable=true,updatable=true)
	@Cascade(org.hibernate.annotations.CascadeType.MERGE)
	private CedenteBean cedente;

	@ManyToOne
	@JoinColumn(name="SAC_ID",insertable=true,updatable=true)
	@Cascade(org.hibernate.annotations.CascadeType.MERGE)
	private SacadoBean sacado;
	
	@Column(name="DPLCT_VENCIMENTO")
	@Temporal(TemporalType.DATE)
	private Date vencimento;
	
	@ManyToOne
	@JoinColumn(name="BORD_ID",insertable=true,updatable=true)
	@Cascade(org.hibernate.annotations.CascadeType.MERGE)
	private BorderoBean bordero;

	@Column(name="DPLCT_VLR_TOTAL")
	private Double valorTotal;

	@Column(name="DPLCT_VLR_DESAGIO")
	private Double valorDesagio;
	
	@Column(name="DPLCT_VLR_SERVICO")
	private Double valorServico;	
	
	@Column(name="DPLCT_VLR_DESP_DPLCT")	
	private Double valorDespDuplicata;
	
	@Column(name="DPLCT_VLR_LQDO")
	private Double valorLiquido;
	
	@Column(name="DPLCT_VLR_IOF")
	private Double valorIof;

	@Column(name="DPLCT_EMISSAO")
	@Temporal(TemporalType.DATE)
	private Date emissao;
	
	@Column(name="DPLCT_SEU_NUMERO")
	private String seuNumero;
	
	@Column(name="DPLCT_VENCIMENTO_REAL")
	@Temporal(TemporalType.DATE)
	private Date vencimentoReal;	
	
	@Column(name="DPLCT_DIAS_COBRA")
	private Integer diasCobrados;
	
	@ManyToOne
	@JoinColumn(name="STTS_TTL_ID",insertable=true,updatable=true)
	@Cascade(org.hibernate.annotations.CascadeType.MERGE)
	private StatusTituloBean status;
	
	@OneToMany(mappedBy="duplicata", fetch=FetchType.EAGER)
	@Cascade(org.hibernate.annotations.CascadeType.ALL)
	private Set<HistoricoDuplicataBean> historicos;
	
	@ManyToMany(fetch=FetchType.EAGER)
	@Fetch(FetchMode.JOIN)
	@Cascade(org.hibernate.annotations.CascadeType.ALL)
	@JoinTable(
			name = "duplicata_lancamento",
			joinColumns={@JoinColumn(name="DPLCT_ID")},
			inverseJoinColumns={@JoinColumn(name="LANCA_ID")}
	)
	private Set<LancamentoBean> lancamentos;


//consulta todas as duplicatas contidas num bordero
public List<DuplicataBean> findDuplicatas(BorderoBean bordero) {
		List<DuplicataBean> retorno = new LinkedList<DuplicataBean>();		
		try {
			session = HibernateUtil.getSession();
			HibernateUtil.beginTransaction();
			Criteria c = session.createCriteria(DuplicataBean.class);
			c.add(Restrictions.eq("bordero", bordero));			
			retorno = c.list();
			HibernateUtil.commitTransaction();			
			return retorno;
		} catch (Exception e) {
			e.printStackTrace();
			HibernateUtil.rollbackTransaction();
		} finally {
			HibernateUtil.closeSession();
			return retorno;
		}		
	}	

Troquei o @Fetch(FetchMode.JOIN) para @Fetch(FetchMode.SUBSELECT) ou @Fetch(FetchMode.SELECT) e funcionou.

Alguem pode me explicar por que?

    @ManyToMany(fetch=FetchType.EAGER)  
    @Fetch(FetchMode.SUBSELECT)
    @Cascade(org.hibernate.annotations.CascadeType.ALL)  
    @JoinTable(  
             name = "duplicata_lancamento",  
             joinColumns={@JoinColumn(name="DPLCT_ID")},  
             inverseJoinColumns={@JoinColumn(name="LANCA_ID")}  
   )  
     private Set<LancamentoBean> lancamentos;