Ajuda com Hibernate

Pessoal,

  1. Tenho uma classe Usuario.
  2. Tenho uma classe Grupo.
  3. Um usuário pode estar em mais de um Grupo e vice-versa.
  4. Ou seja, um relacionamento muitos-para-muitos. Surge, então, a classe GrupoUsuario.

Até aí, tudo bem.

Fiz o mapeamento no Hibernate com Annotations e utilizando o HibernateTools para realizar isso.

Veja o código que estou utilizando para testar a inclusão no Hibernate.


		Usuario usuario = new Usuario();
		usuario.setLogin("userTeste");
		usuario.setNome("Usuário Teste");
		
		Grupo grupo1 = new Grupo(1, "Administradores");
		Grupo grupo2 = new Grupo(2, "Liberação");
		Grupo grupo3 = new Grupo(3, "Preparação");
		
		
		Session session = sessionFactory.openSession();
		Transaction transaction = session.getTransaction();
		transaction.begin();
		
		
		GrupoUsuario grupoUsuario = new GrupoUsuario();
		grupoUsuario.setId(new GrupoUsuarioId(grupo2.getId(), usuario.getId()));
		grupoUsuario.setUsuario(usuario);
		grupoUsuario.setGrupo(grupo2);
		usuario.getGrupoUsuarios().add(grupoUsuario);
		
		grupoUsuario = new GrupoUsuario();
		grupoUsuario.setId(new GrupoUsuarioId(grupo1.getId(), usuario.getId()));
		grupoUsuario.setUsuario(usuario);
		grupoUsuario.setGrupo(grupo1);
		usuario.getGrupoUsuarios().add(grupoUsuario);
		
		
		
		session.save(usuario);
		transaction.commit();

Eu achei que quando eu salvasse o Usuário, o Hibernate pegaria o ID que foi gerado, e incluiria automaticamente nos objetos GrupoUsuario que criei.

Porém, o seguinte erro é gerado:


Cannot insert the value NULL into column 'ID_USUARIO', table 'Reanalise.dbo.GRUPO_USUARIO'; column does not allow nulls. INSERT fails.

Se eu faço isso aqui:

[code]

session.save(usuario);

	Iterator<GrupoUsuario> itGrupoUsuario = usuario.getGrupoUsuarios().iterator();
	while (itGrupoUsuario.hasNext()) {
		itGrupoUsuario.next().getId().setIdUsuario(usuario.getId());
	}

	transaction.commit();

Ou seja, se depois de salvar o usuário eu setar o ID gerado em todos os objetos GrupoUsuario. Aí funciona normalmente.

É isso mesmo que devo fazer?

Abraço e Obrigado

Como é orientação a objetos, não é necessário criar uma nova classe para representar o manyToMany, isto será escencial no seu banco de dados porém na classe não.
Segue um pequeno exemplo de manyToMany, onde um usuário tem Varias ordens de serviço, e cada ordem de serviço tem vários usuários.

@Entity
public class OrdemServico {

	private Long id;

	private Set<Usuario> usuarios;

	@Id
	@GeneratedValue
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	@ManyToMany
	@JoinTable(name = "OrdemServico_Usuario", uniqueConstraints = { @UniqueConstraint(columnNames = {
			"idOrdemServico", "idUsuario" }) }, joinColumns = @JoinColumn(name = "idOrdemServico", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "idUsuario", referencedColumnName = "id"))
	public Set<Usuario> getUsuarios() {
		return usuarios;
	}
}
@Entity
public class Usuario {

	private Long id;

	private Set<OrdemServico> ordemServico;

	@Id
	@GeneratedValue
	public Long getId() {
		return id;
	}

	@ManyToMany(mappedBy="usuarios")
	public Set<OrdemServico> getOrdemServico() {
		return ordemServico;
	}

}

zepunk, interessante. Compreendi o que vc disse.

Mas agora o problema é outro, veja:

Illegal use of mappedBy on both sides of the relationship: br.com.teste.qaqc.bean.Grupo.usuarios

Estou utilizando o Hibernate Tools para gerar os beans com os respectivos annotations. Deixei a opção Detect many-to-many tables habilitada

Veja os respectivos mapeamentos:


Classe Usuario:

	@ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "usuarios")
	public Set<Grupo> getGrupos() {
		return this.grupos;
	}

Classe Grupo

	@ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "grupos")
	public Set<Usuario> getUsuarios() {
		return this.usuarios;
	}

Será que o HibernateTools tá gerando alguma coisa indevida ou eu que não estou sabendo utilizar?

Abraço e Obrigado,

Pessoal,

Resolvi voltando para os hbm.xml.

Não teve jeito, não queria, porém, o prazo é curto e não dá para entender o Annotation agora.

Porém, não foi tão trivial assim.

O plugin HibernateTool não gerou devidamente quando é relacionamento many-to-many.

Eu tive que configurar algumas coisas na mão, no arquivo XML mesmo.

Abraço

cara … vc deve de alguma forma, ao invés de na criação do GrupoUsuario passar o id do usuario e o id do grupo, passar os 2 objetos.

No momento q vc salvar o grupousuario, o hibernate salvará os 2 objetos também…

QQ dúvida, posta aí

Abraço

Márcio,

Veja como está agora:

		SessionFactory sessionFactory;
		//sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
		sessionFactory = new Configuration().configure().buildSessionFactory();
		
		Usuario usuario = new Usuario();
		usuario.setLogin("userTeste25");
		usuario.setNome("Usuário Teste");
		
		Session session = sessionFactory.openSession();
		
		Grupo grupo1 = (Grupo)session.load(Grupo.class, new Integer(1));
		Grupo grupo2 = (Grupo)session.load(Grupo.class, new Integer(2));
		Grupo grupo3 = (Grupo)session.load(Grupo.class, new Integer(3));
		
		Transaction transaction = session.getTransaction();
		transaction.begin();

		usuario.getGrupos().add(grupo3);
		usuario.getGrupos().add(grupo2);
		
		grupo3.getUsuarios().add(usuario);
		grupo2.getUsuarios().add(usuario);
		
		session.save(usuario);
		transaction.commit();

Eu não preciso mais da classe GrupoUsuario, pois ela é apenas uma classe de relacionamento mesmo, nada além das chaves estrangeiras que compõe a chave primária.

Desta forma está funcionando perfeitamente, ou seja, ao criar um usuário ele insere tb na tabela GRUPO_USUARIO (configurada no hbm.xml Usuario e Grupo);

O lance agora é conseguir fazer o mesmo com o Annotation

Veja como ficou os dois hbm.xml


Usuario

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 18/10/2006 15:48:19 by Hibernate Tools 3.2.0.beta7 -->
<hibernate-mapping>
    <class name="br.com.yyy.qaqc.bean.Usuario" table="USUARIO" schema="dbo" catalog="Reanalise">
        <id name="id" type="int">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="login" type="string">
            <column name="LOGIN" length="15" unique="true" />
        </property>
        <property name="nome" type="string">
            <column name="NOME" length="60" not-null="true" />
        </property>
        <property name="senha" type="java.lang.Integer" insert="false" update="false">
            <column name="SENHA" />
        </property>
        <set name="equipes" table="equipe_usuario" cascade="save-update">
            <key>
                <column name="ID_USUARIO" not-null="true" />
            </key>
            <many-to-many entity-name="br.com.yyy.qaqc.bean.Equipe">
                <column name="ID_EQUIPE" not-null="true" />
            </many-to-many>
        </set>
        <set name="reanalises" inverse="true">
            <key>
                <column name="ID_USUARIO_SOLICITANTE" not-null="true" />
            </key>
            <one-to-many class="br.com.yyy.qaqc.bean.Reanalise" />
        </set>
        <set name="grupos" table="grupo_usuario" cascade="save-update">
            <key>
                <column name="ID_USUARIO" not-null="true" />
            </key>
            <many-to-many entity-name="br.com.yyy.qaqc.bean.Grupo">
                <column name="ID_GRUPO" not-null="true" />
            </many-to-many>
        </set>
    </class>
</hibernate-mapping>

Grupo

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 18/10/2006 15:48:19 by Hibernate Tools 3.2.0.beta7 -->
<hibernate-mapping>
    <class name="br.com.sgsgeosol.qaqc.bean.Grupo" table="GRUPO" schema="dbo" catalog="Reanalise">
        <id name="id" type="int">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="descricao" type="string">
            <column name="DESCRICAO" length="30" not-null="true" />
        </property>
        <set name="permissaos" table="permissao_grupo" cascade="save-update">
            <key>
                <column name="ID_GRUPO" not-null="true" />
            </key>
            <many-to-many entity-name="br.com.yyy.qaqc.bean.Permissao">
                <column name="ID_PERMISSAO" not-null="true" />
            </many-to-many>
        </set>
        <set name="usuarios" table="grupo_usuario" inverse="true">
            <key>
                <column name="ID_GRUPO" not-null="true" />
            </key>
            <many-to-many entity-name="br.com.yyy.qaqc.bean.Usuario">
                <column name="ID_USUARIO" not-null="true" />
            </many-to-many>
        </set>
    </class>
</hibernate-mapping>

Desse jeito tá tudo funcionando normalmente.

PS.: No Grupo tb tenho um relacionamento many-to-many com a PERMISSAO, porém não coloquei aqui. Além disso, “permissaos” não é o plural de “permissao”, ficou assim pois o Plugin que gerou automaticamente. Depois eu vou trocar :smiley:

Um Abraço

"