[Dúvida] Hibernate - Relacionamentos!

Olá, pessoal do GUJ!
Tudo bem?

Estou aqui aprendendo sobre as funcionalidades do Hibernate, e me surgiu o pequeno problema:
Bom, tenho duas tabelas no meu Banco de Dados:

Create Table dbo.GruposUsuarios (
Codigo Bigint Not Null Primary Key,
Grupo Varchar(50) Not Null
);
Create Sequence dbo.ProximoGrupoUsuario;

Create Table dbo.Usuarios (
Codigo Bigint Not Null Primary Key,
Usuario Varchar(30) Not Null,
Senha Varchar(20) Not Null,
GrupoUsuario Bigint Not Null,
Foreign Key (GrupoUsuario) References dbo.GruposUsuarios(Codigo)
);
Create Sequence dbo.ProximoUsuario;

Beleza, dá pra ver que há um relacionamento um-para-muitos entre as tabelas GruposUsuarios e Usuarios.

Daí tá… Fui mapear minhas classes do Hibernate, mas não sei como mapear esse relacionamento entre elas. Tentei desse modo:

<hibernate-mapping>

    <class name="digidoc.model.Bean.Usuario" table="Usuarios">

        <id name="codigo" column="codigo" type="java.lang.Long">
            <generator class="native" />
        </id>

        <property name="usuario" not-null="true" column="usuario" type="java.lang.String" />
        <property name="senha" not-null="true" column="senha" type="java.lang.String" />

        <many-to-one name="grupousuario"

        	column="grupousuario"

        	class="digidoc.model.Bean.GrupoUsuario"

        	not-null="true"/>
                
    </class>
</hibernate-mapping>

Pelo visto não tá funcionando, pois o Hibernate me retorna o seguinte erro:

coluna "grupousuario" é do tipo bigint mas expressão é do tipo bytea
  Dica: Você precisará reescrever ou converter a expressão.

Penso que esse erro possa ser pelo fato de eu ter um objeto GrupoUsuario dentro da minha classe Usuario, não sei.
Minha codificação, para teste, está assim:

public class Main
{
    public static void main(String[] args)
    {
        try {

            GrupoUsuario grupo;
            Usuario usuario;

            grupo = new GrupoUsuario();
            grupo.setGrupoUsuario("Administradores");
            HibernateHelper.saveOrUpdate(grupo);
            
            grupo = new GrupoUsuario();
            grupo.setGrupoUsuario("Estagiários");
            HibernateHelper.saveOrUpdate(grupo);
            
            grupo = (GrupoUsuario) HibernateHelper.find(GrupoUsuario.class, new Long(1) );

            usuario = new Usuario();
            usuario.setUsuario("nicolas");
            usuario.setSenha("123456");
            usuario.setGrupoUsuario(grupo);

            HibernateHelper.saveOrUpdate(usuario);
            
            HibernateHelper.commitTransaction();  // <--- - é aqui que dá o erro, na hora de executar um Commit na operação!
        } 
        catch (HibernateException err) {

            err.printStackTrace();
        }
        catch (SQLException err) {

            err.printStackTrace();
        }
    }
}

Qualquer ajuda será bem-vinda!
Valeu, galera, abraços! :smiley:

Nicolas,

Faltou só colocar os códigos das duas entidades.

Aliás que, se ‘grupousuario’ é somente uma tabela de relacionamento (sem atributos próprios), ela não precisará ter entidade própria. Um @ManyToMany entre Grupo e Usuario funciona muitíssimo bem :wink:

Ah, verdade! My fault, my fault…

Entidade Usuário:

@Entity
@Table(name="Usuarios", schema="dbo")
@SequenceGenerator(name="sequenceUsuarios", sequenceName="dbo.ProximoUsuario",
                   initialValue=1, allocationSize=1)
                   
public class Usuario implements Serializable
{
    private Long codigo;
    private String usuario;
    private String senha;
    private GrupoUsuario grupoUsuario;

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="sequenceUsuarios")
    @Column(name="Codigo")
    public Long getCodigo() { return codigo; }

    @Column(name="Usuario", nullable=false, length=40)
    public String getUsuario() { return usuario; }

    @Column(name="Senha", nullable=false, length=30)
    public String getSenha() { return senha; }

    @Column(name="GrupoUsuario", nullable=false)
    public GrupoUsuario getGrupoUsuario() { return grupoUsuario; }

    public void setCodigo(Long codigo) { this.codigo = codigo; }
    public void setUsuario(String usuario) { this.usuario = usuario; }
    public void setSenha(String senha) { this.senha = senha; }
    public void setGrupoUsuario(GrupoUsuario grupoUsuario) { this.grupoUsuario = grupoUsuario; }
}

Entidade GrupoUsuario:

@Entity
@Table(name="GruposUsuarios", schema="dbo")
@SequenceGenerator(name="sequenceGruposUsuarios", sequenceName="dbo.ProximoGrupoUsuario",
                   initialValue=1, allocationSize=1)
                   
public class GrupoUsuario implements Serializable
{
    private Long codigo;
    private String grupoUsuario;

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="sequenceGruposUsuarios")
    @Column(name="Codigo")
    public Long getCodigo() { return codigo; }

    @Column(name="GrupoUsuario", length=40, nullable=false)
    public String getGrupoUsuario() { return grupoUsuario; }

    public void setCodigo(Long codigo) { this.codigo = codigo; }
    public void setGrupoUsuario(String grupoUsuario) { this.grupoUsuario = grupoUsuario; }
}

:smiley:

Editando…
Falei besteira! :oops:

Nicolas,

Na tua entidade ‘Usuario’, você deve ter uma LISTA de ‘grupoUsuario’. É isso que o hibernate tá xilicando.
A mesma coisa para ‘Grupo’, precisará de uma lista de ‘grupoUsuario’.

Mas, de novo, repito: eu acho melhor não ter a entidade ‘grupoUsuario’, e somente grupo e usuário, manyToMany :wink:

E deixa só eu esclarecer: vc não está misturando XML E annotation, está?

[quote=CintiaDR]Nicolas,

Na tua entidade ‘Usuario’, você deve ter uma LISTA de ‘grupoUsuario’. É isso que o hibernate tá xilicando.
A mesma coisa para ‘Grupo’, precisará de uma lista de ‘grupoUsuario’.

Mas, de novo, repito: eu acho melhor não ter a entidade ‘grupoUsuario’, e somente grupo e usuário, manyToMany ;)[/quote]

Cintia,
Obrigado pelas respostas.

Na verdade, a ideia é a seguinte: “um usuário pertence a um grupo, e um grupo pode conter um ou mais usuários”. Ou seja, é um relacionamento um-para-muitos, concorda? Se um usuário só pertence a um grupo, porque eu deveria ter uma coleção de GrupoUsuario dentro da entidade Usuario?

A ideia é o usuário pertencer a um grupo, e este grupo possuir várias permissões. Nesse caso, aí sim teremos uma coleção de Permissoes dentro da entidade GrupoUsuario, certo?

A relação ManyToMany funcionará para a ideia das permissões, e não para o relacionamento do usuário e seu grupo.

Não entendi esse “misturar” XML com Annotation… hehe
Mas se esse seu “misturar” significa colocar XML e Annotations em uma mesma codificação, não. Está exatamente como coloquei nos posts anteriores: as annotations dentro das entidades, e os XML como mapeamento das classes. É assim o jeito correto, né?

Valeu pela ajuda! :]

Realmente, desculpe, entendi que era N:N entre grupos e usuários, mas vc não citou isso em hora nenhuma.
Então, é um OneToMany. Fiz uma confusão também com o nome das tuas classes

Fiz assim:

Create Table dbo.GruposUsuarios (
Codigo Bigint PRIMARY KEY IDENTITY,
Grupo Varchar(50) Not Null
)


Create Table dbo.Usuarios (
Codigo Bigint PRIMARY KEY IDENTITY,
Usuario Varchar(30) Not Null,
Senha Varchar(20) Not Null,
GrupoUsuario Bigint Not Null,
Foreign Key (GrupoUsuario) References dbo.GruposUsuarios(Codigo)
)

E as entidades:

@Entity
@Table(name="Usuarios", schema="dbo")                
public class Usuario implements Serializable
{
    private Long codigo;
    private String usuario;
    private String senha;
    private GrupoUsuario grupo;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="Codigo")
    public Long getCodigo() { return codigo; }

    @Column(name="Usuario", nullable=false, length=40)
    public String getUsuario() { return usuario; }

    @Column(name="Senha", nullable=false, length=30)
    public String getSenha() { return senha; }

    @ManyToOne
    @JoinColumn(name="GrupoUsuario", nullable=false)
    public GrupoUsuario getGrupo() { return grupo; }

    public void setCodigo(Long codigo) { this.codigo = codigo; }
    public void setUsuario(String usuario) { this.usuario = usuario; }
    public void setSenha(String senha) { this.senha = senha; }
    public void setGrupo(GrupoUsuario grupoUsuario) { this.grupo = grupoUsuario; }
}

@Entity
@Table(name="GruposUsuarios", schema="dbo")
public class GrupoUsuario implements Serializable
{
    private Long codigo;
    private String nome;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="Codigo")
    public Long getCodigo() { return codigo; }

    @Column(name="Grupo", length=40, nullable=false)
    public String getNome() { return nome; }

    public void setCodigo(Long codigo) { this.codigo = codigo; }
    public void setNome(String nome) { this.nome = nome; }
}

No persistence.xml, só inclui as duas classes (o nome delas):

		&lt;class&gt;pacote.GrupoUsuario&lt;/class&gt;	
		&lt;class&gt;pacote.Usuario&lt;/class&gt;	

E SÓ. Fazer um projeto com HBM e também anotação não faz sentido.
Funcionou isso aí encima. Mudei um pouco o nome de algumas coisas prq estavam me confundindo. Usei o MS-SQL, e pelo menos a versão que eu uso não dá pra usar sequence: substitui por identity.

Oi, Cintia!

Muito obrigado, funcionou legal. Agora estou tentando aprender a mapear outros relacionamentos; qualquer coisa, venho apurrinhar mais um pouco. :]

Valeu!!