E aí pessoal… boa tarde.
No desenvolvimento de um sistema, onde uso hibernate, spring e jsf, precisei mapear as duas entidades a seguir.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "documento")
public class Documento implements Serializable {
private static final long serialVersionUID = 1l;
private Integer id;
private Set<Movimento> movimentos = new LinkedHashSet<Movimento>();
...
/**
* @return the movimentos
*/
@OneToMany(mappedBy = "documento", fetch = FetchType.EAGER)
@OrderBy("envio")
public Set<Movimento> getMovimentos() {
return movimentos;
}
}
@Entity
@Table(name = "movimento")
public class Movimento implements Serializable {
private static final long serialVersionUID = 1l;
private MovimentoPK movimentoPK;
private Documento documento;
...
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "cd_documento", referencedColumnName = "cd_documento", insertable = false, updatable = false)
@Cascade(CascadeType.SAVE_UPDATE)
public Documento getDocumento() {
return documento;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Movimento other = (Movimento) obj;
if (this.movimentoPK != other.movimentoPK && (this.movimentoPK == null || !this.movimentoPK.equals(other.movimentoPK))) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 7;
hash = 47 * hash + (this.movimentoPK != null ? this.movimentoPK.hashCode() : 0);
return hash;
}
}
Também foi necessário mapear a classe MovimentoPK:
@Embeddable
public class MovimentoPK implements Serializable {
private static final long serialVersionUID = 1l;
private Integer documentoId;
private Integer origemId;
private Integer destinoId;
private Date envio;
...
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final MovimentoPK other = (MovimentoPK) obj;
if (this.documentoId != other.documentoId && (this.documentoId == null || !this.documentoId.equals(other.documentoId))) {
return false;
}
if (this.origemId != other.origemId && (this.origemId == null || !this.origemId.equals(other.origemId))) {
return false;
}
if (this.destinoId != other.destinoId && (this.destinoId == null || !this.destinoId.equals(other.destinoId))) {
return false;
}
if (this.envio != other.envio && (this.envio == null || !this.envio.equals(other.envio))) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 5;
hash = 89 * hash + (this.documentoId != null ? this.documentoId.hashCode() : 0);
hash = 89 * hash + (this.origemId != null ? this.origemId.hashCode() : 0);
hash = 89 * hash + (this.destinoId != null ? this.destinoId.hashCode() : 0);
hash = 89 * hash + (this.envio != null ? this.envio.hashCode() : 0);
return hash;
}
}
Também foi necessário se realizar a seguinte consulta:
@Repository("documentoRepository")
public class DocumentoRepository extends GenericHibernateBasicRepository<Documento> {
private static final long serialVersionUID = 1L;
public DocumentoRepository() {
}
public Collection<Documento> getAllFromDocumentoFilterData(DocumentoFilterData documentoFilterData) {
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Documento.class).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
if (documentoFilterData.getIdDocumento() != null) {
detachedCriteria.add(Restrictions.eq("id", documentoFilterData.getIdDocumento()));
}
detachedCriteria.addOrder(Order.desc("emissao"));
return this.getAll(detachedCriteria);
}
Ocorre que, ao se realizar a consulta o hibernate preenche a coleção de movimento na classe Documento com valores repetidos de Movimento. Utilizo o Criteria.DISTINCT_ROOT_ENTITY ResultTransformer, no entanto, não consigo recuper o objeto da forma correta. Alterei a interface da coleção(de List para Set). Resolveu o problema pois o Set não permite resultados duplicados, no entanto é muito ineficiente utilizar um Set pois eu preciso iterar pela coleção, além de acessar valores indexados. Sei que o hibernate se utiliza da interface da Coleção para recuperar a semântica da associação, no entanto, espero que ele não nos limite a escolher uma estrutura de dados menos adequada.
Agradeço desde já, se alguém puder me auxiliar, principalmente, com a consulta.