Estou utilizando Vraptor com Hibernate e gostaria de uma dica para melhorar minha implantação:
Tenho que um cadastro de contas que tem um relacionamento NxN com Usuarios, utilizando uma tabela do meio com colunas extras.
ContasxContasUsuariosxUsuarios
No form do cadastro de contas, eu listo todos os usuários que podem ser associados aquela conta com uma checkbox ao lado de cada, e
um inputText para adicionar observações.
para que ao cadastrar uma conta o usuário possa escolher quais usuários serão associados com aquela conta.
Eu implementei desta forma:
Ao submeter o form de cadastro da conta, também envio a lista dos ids dos usuários a serem associados para esta conta.
no form de conta:
[code]<c:forEach items="${usuarios}" var=“usuario” varStatus=“s”>
${usuario.nome}
[/code]
no controller:
public void add(Conta conta, List<String> usuariosSelecionados, List<Integer> observacaoUsuario) {
E no controller eu busco cada usuário pelo id e associo a esta conta e no final gravo a conta.
Está funcionando, mas não gostei muito da forma que ficou, queria dicas de implementar isso de acordo boas práticas.
você não precisa buscar cada usuário do banco, só dele ter o id o hibernate já consegue relacionar…
então vc poderia usar os parâmetros:
conta.usuarios[0].id = 2
conta.usuarios[1].id = 5
conta.usuarios[3].id = 7
....
Não consegui pois minhas entidades Conta e Usuarios foram mapeados seguindo isso aqui: http://www.mkyong.com/hibernate/hibernate-many-to-many-example-join-table-extra-column-annotation/
Então dentro de Conta eu tenho um:
private Set<ContaUsuario> usuarios = new HashSet<ContaUsuario>(0);
e a classe ContaUsuario ficou assim:
[code]@Entity
@Table(name = “conta_usuario”)
@AssociationOverrides({
@AssociationOverride(name = “pk.conta”,
joinColumns = @JoinColumn(name = “conta_id”)),
@AssociationOverride(name = “pk.usuario”,
joinColumns = @JoinColumn(name = “usuario_id”)) })
public class ContaUsuario implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = -5716086006460889389L;
private ContaUsuarioId pk = new ContaUsuarioId();
private Double valor;
public ContaUsuario() {
}
@EmbeddedId
public ContaUsuarioId getPk() {
return pk;
}
public void setPk(ContaUsuarioId pk) {
this.pk = pk;
}
@Transient
public Conta getConta() {
return getPk().getConta();
}
public void setConta(Conta stock) {
getPk().setConta(stock);
}
@Transient
public Usuario getUsuario() {
return getPk().getUsuario();
}
public void setUsuario(Usuario usuario) {
getPk().setUsuario(usuario);
}
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
ContaUsuario that = (ContaUsuario) o;
if (getPk() != null ? !getPk().equals(that.getPk())
: that.getPk() != null)
return false;
return true;
}
public int hashCode() {
return (getPk() != null ? getPk().hashCode() : 0);
}
public void setValor(Double valor) {
this.valor = valor;
}
public Double getValor() {
return valor;
}
} [/code]
Então tem alguma outra forma para o hibernate cuidar disso para mim, para melhorar minha implementação?
se o getter e o setter usarem List ao inves de Set vai funcionar…
na verdade, o VRaptor usa os getters e setters, então se vc tiver um getUsuarios() e um setUsuarios() que retorna os usuários de acordo com o que está no ContaUsuario deve funcionar
Mudei de Set para List e mudei a view para
[code]<c:forEach items="${usuarios}" var=“usuario” varStatus=“s”>
${usuario.nome}
[/code]
O que acontece agora é:
Ele esta salvando o usuario_id e valor na tabela conta_usuario sem gravar o id da nova conta(conta_id) além de que grava uma linha a mais na tabela conta_usuario, com um usuario_id que não existe(está parecendo algum incremento) e null em conta_id e valor.
O que deve ser?
vc ainda tá usando um parâmetro adicional…
troque para usar a conta:
<input ... name="conta.usuarios[${s.index}].id"
ou algo do tipo
ops…copiei o código errado…
na verdade já esta assim:
contas\form.jsp
[code]
<c:forEach items="${usuarios}" var=“usuario” varStatus=“s”>
${usuario.nome}
[/code]
O que eu percebi que acontece é que ele sempre vai tentar gravar todos usuariosSelecionados, independente de marcar ou não checkbox, que no caso só está servindo para enviar o id do usuário se marcado.
Acho que vou criar uma função javascript que seja acionada no onclick do checkbox e insira um hidden com o valor que quero gravar.
hum… é acho que isso talvez não funcione mesmo…
o que vc precisa fazer é pegar a lista dos usuários, buscar os ContaUsuario correspondentes no banco, e fazer a alteração
No fim usei jquery, fiz algo parecido com isso aqui: http://jsbin.com/itugug/edit
dessa forma eu adiciono/removo input hidden com o id do usuário que quero associar a nova conta.
Lucas, Valeu pela ajuda!