Problema com @manytoone e @onetomany no hibernate

Bom dia,

Tenho 3 Entitys, sendo Usuario, Regra e RegraUsuario.
A Usuario armazena o cadastro do usuario, a Regra Armazena as Regras e a RegraUsuario associa as regras aos usuarios. segue abaixo os codigos das entitys:

Usuario:

@Entity
@Table(name="INTRA_NESIC_USUARIO")
public class Usuario {
	@Id @GeneratedValue
	private Long id;
	@Column(updatable = true, nullable = false)
	private String nome;
	@Column(updatable = true, nullable = false)
	private String login;
	@Column(updatable = true, nullable = false)
	private String senha;
	@Column(columnDefinition = "date DEFAULT GETDATE()", insertable = false, updatable = true, nullable = false) 
	private Date datacad; 
	@Column(columnDefinition = "int default 0", insertable = false, updatable = true, nullable = false) 
	private Long flgatv ; 
	@OneToMany(mappedBy="usuario", cascade=CascadeType.ALL)
	private Collection<RegraUsuario> regraUsuarioList;
	
	//getters e setters

Regra:

@Entity
@Table(name="INTRA_NESIC_REGRA")
public class Regra {
	@Id @GeneratedValue
	private Long id;
	@Column(updatable = true, nullable = false)
	private String regra;
	@Column(updatable = true, nullable = false)
	private String descricao;
	@Column(columnDefinition = "date DEFAULT GETDATE()", insertable = false, updatable = true, nullable = false) 
	private Date datacad; 
	@Column(columnDefinition = "int default 0", insertable = false, updatable = true, nullable = false) 
	private Long flgatv ;
	@OneToMany(mappedBy="regra", cascade=CascadeType.ALL)
	private Collection<RegraUsuario> regraUsuarioList;
	
	//getters e setters

RegraUsuario:

@Entity
@Table(name="INTRA_NESIC_REGRA_USUARIO")
public class RegraUsuario {
	@Id @GeneratedValue
	private Long id;
	@ManyToOne @JoinColumn(name="usuario_id")
	private Usuario usuario;
	@ManyToOne @JoinColumn(name="regra_id")
	private Regra regra;
	@Column(columnDefinition = "date DEFAULT GETDATE()", insertable = false, updatable = false, nullable = false) 
	private Date datacad; 
	@Column(columnDefinition = "int default 0", insertable = false, updatable = false, nullable = false) 
	private Long flgatv ;
	
	//getters e setters

JSP para gravar um usuario ja escolhendo as devidas regras que o usuário terá:

[code]

" method="POST"> Criar novo usuário Nome: Regra: ${regra.regra } Login: Senha: Confirme a senha: Enviar [/code]

Bom, agora o problema, quando cadastro o usuario ele é inserido normalmente na tabela Usuario porem o id dele vai com valor null para a tabela RegraUsuario, segue a tabela abaixo com o problema:

Entenderam?? tudo é cadastrado normalmente, só o usuario_id da tabela RegraUsuario que por algum motivo é gravado sempre null, alguem sabe o q fazer?? ja fiz de tudo e nao encontrei o problema.

Acredito que o problema esteja no @ManyToOne(fetch=FetchType.LAZY) na classe RegraUsuario.

Ah sim, esse Lazy é justamente um teste, esqueci de tirar ele pra postar aqui, vou editar o topico, sem o Lazy continua o mesmo problema.

Pronto, deixei as classe da maneira original de como quando começou a dar o erro

Agora que você colocou as linhas do banco deu pra entender melhor.

  • Antes de persistir o usuário, verifique a lista regraUsuarioList.
  • Se você postar o seu controlller vai faciliar o entendimento do problema também, não entendi como funciona a associação dos usuários com as regras, aparentemente você já tem uma lista de regras de usuário e depois só associa essas regras ao usuário.

Exatamente, ja tenho a tabela de regras com as regras cadastradas, ae quando cadastro o usuario ele apenas associa pelas chaves estrangeiras na tabela RegraUsuario, sendo assim um usuario pode ter varias regras. segue abaixo o controller do Usuario:

[code]
@Resource
public class UsuariosController {

private final UsuarioDAO dao;
private final RegraDAO daoRegra;
private final Result result;
private final Validator validator;
private final UsuarioWeb usuarioWeb;

public UsuariosController(UsuarioDAO dao, Result result, Validator validator, 
								UsuarioWeb usuarioWeb, RegraDAO daoRegra) {
	this.dao = dao;
	this.daoRegra = daoRegra;
	this.result = result;
	this.validator = validator;
	this.usuarioWeb = usuarioWeb;
}

@Post @Path("/usuarios")
public void adiciona(Usuario usuario) {
	if (dao.existeUsuario(usuario)) {
		validator.add(new ValidationMessage("Login já existe", "usuario.login"));
	}
	validator.onErrorUsePageOf(UsuariosController.class).novo();
	
	dao.adiciona(usuario);
	result.redirectTo("/");
}

@Path("/logout")
public void logout() {
	usuarioWeb.logout();
	result.redirectTo("/");
}

@Get @Path("/")
public void loginForm() {
}

@Path("/negado")
public void negado(){
}

public void novo() {
	result.include("regraUsuarioList",daoRegra.lista());
}

}[/code]

[quote=renatomattos2912]Exatamente, ja tenho a tabela de regras com as regras cadastradas, ae quando cadastro o usuario ele apenas associa pelas chaves estrangeiras na tabela RegraUsuario, sendo assim um usuario pode ter varias regras. segue abaixo o controller do Usuario:

[code]
@Resource
public class UsuariosController {

private final UsuarioDAO dao;
private final RegraDAO daoRegra;
private final Result result;
private final Validator validator;
private final UsuarioWeb usuarioWeb;

public UsuariosController(UsuarioDAO dao, Result result, Validator validator, 
								UsuarioWeb usuarioWeb, RegraDAO daoRegra) {
	this.dao = dao;
	this.daoRegra = daoRegra;
	this.result = result;
	this.validator = validator;
	this.usuarioWeb = usuarioWeb;
}

@Post @Path("/usuarios")
public void adiciona(Usuario usuario) {
	if (dao.existeUsuario(usuario)) {
		validator.add(new ValidationMessage("Login já existe", "usuario.login"));
	}
	validator.onErrorUsePageOf(UsuariosController.class).novo();
	
	dao.adiciona(usuario);
	result.redirectTo("/");
}

@Path("/logout")
public void logout() {
	usuarioWeb.logout();
	result.redirectTo("/");
}

@Get @Path("/")
public void loginForm() {
}

@Path("/negado")
public void negado(){
}

public void novo() {
	result.include("regraUsuarioList",daoRegra.lista());
}

}[/code][/quote]

Então não seria um ManyToMany? Um Usuário pode ter várias regras e uma regra pode ser de vários usuários?

Então, eu sou iniciante ainda e nao manjo dessa parte, porem pensei o mesmo que vc quando comecei a modelagem mas ae achei um totorial na internet que tem a estrutura de tabelas bem parecida com a que montei, por isso fiz dessa forma (http://www.wbotelhos.com/2011/12/06/hibernate-relacionamento-manytomany-com-atributos)

Mas segue abaixo as minhas tabelas, caso vc esteja certo quanto ao manytomany, onde eu alteraria no meu codigo?? na classe regra e usuario? eu trocaria onde esta @onetoMany por @manytomany??

Usuario:

Regra:

RegraUsuario:

[quote=renatomattos2912]Então, eu sou iniciante ainda e nao manjo dessa parte, porem pensei o mesmo que vc quando comecei a modelagem mas ae achei um totorial na internet que tem a estrutura de tabelas bem parecida com a que montei, por isso fiz dessa forma (http://www.wbotelhos.com/2011/12/06/hibernate-relacionamento-manytomany-com-atributos)

Mas segue abaixo as minhas tabelas, caso vc esteja certo quanto ao manytomany, onde eu alteraria no meu codigo?? na classe regra e usuario? eu trocaria onde esta @onetoMany por @manytomany??

Usuario:

Regra:

RegraUsuario:
[/quote]
Eu, particularmente não gosto muito desse modelo por está mais próximo do modelo relacional do que do modelo OO, você poderia fazer um ManyToMany com atributos num relacionamento utilizando um mapa por exemplo.

Nesse caso o que está acontecendo é que você já tem as RegraUsuario persistidas no banco enquanto os Usuários ainda não estão persistidos, então você tem que persistir os usuários e fazer um merge das RegraUsuario para que o usuario_id seja atualizado nessa tabela. Você tem várias formas de contornar esse problema, mudando a forma como seu relacionamento é feito, mudando a lógica do controller ou mudando a sua view, mas para isso você precisa enxergar o problema.

A primeira falha que eu vejo é que regra_id e usuario_id não são obrigatórios no banco.
VocÊ poderia postar o código do UsuarioDAO.adiciona() ?

e como eu mudaria a forma do relacionamento?? tiraria a tabela intermediaria? mas isso nao deixaria uma confusão nas tabelas de usuario e de regra ja que ficariam os registros repetidos para cada regra que o usuario tiver na propria tabela do usuario?? nao tiraria um pouco do objetivo de cada tabela? vou pesquisar sobre o merge para ver se a forma mais facil de resolver este problema.

segue o codigo:

[code]
@Component
public class UsuarioDAO {

public boolean existeUsuario(Usuario usuario) {
	Usuario encontrado = (Usuario) HibernateUtil.currentSession().createCriteria(Usuario.class)
	.add(Restrictions.eq("login", usuario.getLogin()))
	.uniqueResult();
	return encontrado != null;
}

public void adiciona(Usuario usuario) {
	HibernateUtil.currentSession().save(usuario);
}

public Usuario carrega(Usuario usuario) {
	return (Usuario) HibernateUtil.currentSession().createCriteria(Usuario.class)
	.add(Restrictions.eq("login", usuario.getLogin()))
	.add(Restrictions.eq("senha", usuario.getSenha()))
	.uniqueResult();
}

}[/code]

não consegui utilizar o merge, alguem teria algum exemplo de como eu usaria merge para resolver este meu problema?

Bom dia pessoal, ainda nao consegui resolver, tentei de varias formas ontem e nao sai do lugar, ainda preciso da ajuda de vcs.

opa galera, andei dando uma mexida e agora meu problema mudou, acho que estou no caminho certo mas ainda nao cheguei onde eu quero.

Alterei o metodo de adição de usuario no DAO e ficou assim:

public void adiciona(Usuario usuario) {
	RegraUsuario regraUsuario = new RegraUsuario();
	regraUsuario.setUsuario(usuario);
	HibernateUtil.currentSession().merge(regraUsuario);
}

porem quando tudo é adicionado no banco ao inves de associar o usuario_id ao regra_id, ele adiciona primeiro os regra_id e depois em outro registro o usuario_id:

Alguem sabe como resolver?

ALGUEM???