Qual a melhor maneira?

Pessoal, eu queria saber qual é a melhor maneira de implementar a seguinte situação:
Vamos supor que a pessoa faça um cadastro, e alguns itens são combobox, ou seja, possuem opções já definidas como resposta. Algumas delas são de múltipla escolha (interesses) e outras de única (sexo, profissao).
No banco de dados, acredito que possa ficar assim:

[quote]USUARIO

  • id: int
  • nome: string
  • sexo: int
  • profissao: int
    ?

INTERESSES_USUARIO

  • id_usuario: int
  • id_interesse: int

INTERESSES

  • id: int
  • descricao: string

SEXO

  • id: int
  • descricao: string

PROFISSOES

  • id: int
  • descricao: string[/quote]

Esta seria a melhor maneira? Eu sei que o MySQL tem umas opções de enum. Mas e quando criamos uma profissão nova, temos que mexer na tabela e no código Java, né?

E no código Java? A melhor maneira é como? Criar um VO, por exemplo, Sexo, com id e descricao? Criar um enum do Java? (Daí cai no mesmo dilema: se acrescentarmos mais uma informação ao banco de dados temos que colocar esta nova opção no enum, recompilar?) Eu uma vez eu vi um código em que o cara fazia uma classe Enumeration. Não sei se ele herdou da do Java, mas em vez de fazer enum Profissoes { ADVOGADO, MEDICO } ele criou uma classe com vários atributos estáticos do próprio tipo da classe, e que incrementava automaticamente? Algo mais ou menos assim:

[code]class Profissoes { // não lembro se herda de Enumeration
public static Profissoes ADVOGADO = new Profissoes(“Advogado”);
public static Profissoes MEDICO = new Profissoes(“Médico”);
private static int counter = 0;
private int id;
private String descricao;

public Profissoes(String desc) {
    counter++;
    id = counter;
    descricao = desc;
}

// getters de id e descricao.

}[/code]

Não sei se existe alguma outra maneira, mas como isso é comum demais acredito que tenha algo que não precisamos mexer em dois lugares quando precisar mudar as opções, seja deletando, incluindo ou alterando-as.

Grato.

Eu não sei se vc usa algum framework de persistência, tipo JPA ou Hibernate, mas ajuda nessas situações :wink: Usualmente criamos as classes e fazemos um espelho delas no banco.

Então vou definir as classes Usuario, Interesses e Profissoes. Usuário tem uma lista de interesses, interesses tem uma lista de usuários, e um usuário só tem uma profissão.

‘Sexo’ só existem dois. Isso não vai mudar - quer dizer, se mudar vai levar alguns muitos anos e valerá a pena compilar de novo. Nesses casos, eu acho mais simples na própria classe Usuario fazer um enum, e guardar no banco ‘F’ ou ‘M’ (‘1’ /‘2’; ou como vc preferir distinguir os sexos!)

Para enumerados que crescem muito (veja, mas que mesmo assim não são cadastrados diretamente no sistema) tipo profissões, que é uma grande lista, eu acho que eu iria cadastrar direto no banco de dados, e carregar de lá sempre.

É o que eu faria, prq acho mais fácil. Sei lá.

Mas aí como você faria para carregar no Java do Banco de dados? Do jeito que eu fiz não ia ter como fazer?

Eu havia usado Hibernate para fazer isso, mas na teoria seria simplesmente pegar todos os dados por SELECT quando necessário e inserir um por um numa lista. For, ForEach, While, algo assim.

O jeito que vc fez é OK. Dá para colocar um monte de static num objeto, e salvar tranquilamente - sem persistir quais são as profissões.

Veja, vc não precisa colocar os enumerados no Java E no banco, escolha somente uma dessas abordagens para cada item.

Então as maneiras de fazer :

  1. Criar uma tabela no Banco com todos os valores (ou enum no banco, tanto faz) e carregar para o java sempre que necessário
  2. Criar uma classe com todos os itens (static objects ou enum) e salvar no banco só uma referência ao item.

Não há replicação dessa maneira. Na primeira não precisa recompilar em caso de mudanças, na segunda sim. Eu prefiro a primeira pela facilidade de testar e debuggar (ah, não adianta, eu gosto de olhar no banco), mas vc pode fazer qualquer uma. E claro, mais acessos ao banco custam um pouco mais caro, e vc em que povoar a tabela antes… Vai do gosto do cliente, mas ambas funcionam.

Não sei se estou enchendo, mas tem como você mostrar um exemplo com código destas opções? Algo bem rápido mais, tipo como eu fiz. Esta segunda opção não entendi muito bem?

Também achei estranho essa tabela sexo. Mesmo que vc queria usar algo como ‘localização’ não justifica IMHO.

No mais, aqui tem 2 tutoriais de Hibernate 3:
http://www.guj.com.br/java.tutorial.artigo.174.1.guj
http://www.guj.com.br/java.tutorial.artigo.182.1.guj

Com java 1.5 pra cima vc pode configurar tanto via XML quando Programaticamente (atraves de @anotações)

*** Opção 1 ***

class Profissoes {  // essa classe busca no banco todos as profissoes
  //for cada um, insere nessa lista
  List ProfissoesQueExistem; 
  /*etc etc etc*/

}

Nessa opção, existe uma tabela com todas as profissões previamente cadastradas.
Isso vai salvar no banco:
Usuario(id, nome, sexo, profissoes) = (1, ‘Dr. Fulaninho’, ‘M’, 1)
Usuario(id, nome, sexo, profissoes) = (2, ‘Dr. Fulaninho2’, ‘M’, 2)

Profissao(id, descricao) = (1, ‘Medico’)
Profissao(id, descricao) = (2, ‘Advogado’)

*** Opção 2 ***

class Profissoes {  // essa classe e um enum dá na mesma!
  public static int ADVOGADO = 0;  
  public static int MEDICO = 1;  
}

Isso vai salvar no banco:
Usuario(id, nome, sexo, profissoes) = (‘1’, ‘Dr. Fulaninho’, ‘M’, ‘0’)
Usuario(id, nome, sexo, profissoes) = (‘2’, ‘Dr. Fulaninho2’, ‘M’, ‘1’)

E não vai existir no banco uma tabela chamada ‘Profissoes’, tão pouco o campo profissoes será uma foreign key! E no java, vc sabe quem é profissão 0 ou 1…


Mesmo assim, vc entendendo isso, é interessante vc olhar o hibernate… Ajuda pacas e cotias!

Vocês estão misturando tudo: telas com classes, classes com tabelas e campos do banco de dados, etc. Java é uma linguagem orientada a objetos, enquanto o banco que você está utilizando é relacional. Há, portanto, uma diferença no modo de pensar e projetar as suas classes e suas tabelas. Esta “diferença” é conhecida como “Impedância objeto-relacional” ou “Object-Relational Impedance Mismatch”.
O ideal, já que está utilizando uma linguagem de programação orientada a objetos (Java, no seu caso), é modelar o domínio da sua aplicação independentemente. Depois, um framework de persistência (Hibernate, por exemplo) pode te ajudar a relacionar os seus objetos de domínio e as suas tabelas do banco de dados. E quando for pensar na relação das suas telas (clientes) com o seu domínio, estude um pouco “Service Layer”. Seguem alguns links que podem ajudar a clarear as idéias (eu sei que é muita coisa pra quem não tem muita experiência com OO):

Object-Relational Impedance Mismatch - http://www.agiledata.org/essays/impedanceMismatch.html
Mapping Objects to Relational DataBases - http://www.agiledata.org/essays/mappingObjects.html
Service Layer - http://www.martinfowler.com/eaaCatalog/serviceLayer.html

OBS: JPA é uma especificação e não um framework. Hibernate sim é um framework, e implementa a JPA.

Ih, sabia não, foi mal. Só usei hibernate até hj 8)

Ok, concordo com vc que tá uma salada classe com tabela, até prq acho que é essa a dúvida dele (tela não que eu ainda não vi :lol: )
A pergunta dele era se havia algum jeito de não repetir o mesmo enum no java e no banco. Veja, é um enum, não uma classe comum :smiley:

Não desmerecendo seus links ! A gente teria que sempre programar como se o mantenedor do nosso código fosse um serial killer que sabe onde moramos (plagiando o avatar de alguém). Mas a gente não faz sempre hehe :slight_smile: Anyway, um puxão de orelhas é sempre válido

A minha pergunta foi justamente pra não misturar as coisas. Eu queria saber a melhor maneira (eu até coloquei esse post na área de arquitetura e design patterns, mas ninguém deu atenção lá) de implementar isso, no Java. E queria saber como isso seria refletido no BD.

Por exemplo, ao meu ver, eu precisava apenas disso:

[code]class Profissao {
private String descricao;

public Profissao(String nome) {
    descricao = nome;
}

public String toString() {
    return descricao;
}

}[/code]

Em um determinado momento: pessoa.setProfissao(ProfissaoDAO.getProfissoes()[1]); // claro que coloquei assim para simplificar, direto a profissão 1.

Daria certo? Bom, acho que sim. Mas em uma hora eu teria que armanezar isso, persistir. Eu vou ter que enfiar uma coisinha, um id, mesmo que isso não faça sentido algum “pro domínio”. Daí que começam minhas dúvidas, porque eu acho errado essa coisa de id/descrição? Ou pelo menos que deva existir uma forma mais “moderna”.

Se não me engano, se eu quiser usar CMP, beans e tal, eu teria que implementar uma chave de qualquer jeito. Não iria fugir desta coisa “feia”! :frowning:

Bom, depois de tudo isso, já conversei com várias pessoas e cada uma acha uma coisa.

Ignorando o banco de dados completamente, eu ainda tenho minhas dúvidas se vale em OO a pena ou criar uma classe para Profissões. E se é melhor modelar as profissões como um ENUM de usuario, ou como um lista de constantes.

Está me parecendo que é uma questão de gosto… mzugaib, como vc acha melhor de manter isso na memória?

Manter na memória?
Bom, eu optaria pela solução em que precisaria mexer menos em código, de preferência nada, quando alterar.
:frowning:

Poxa, não tem nenhum design pattern?

Se for para alterar menos código, isto é, nenhum, a solução do banco de dados te serve. Mas não sei se é politicamente correta. Vou tentar ver uns paterns, mas não me lembro de nenhum parecido de cabeça… :cry:

Se eu conseguir alguma coisa eu posto aqui.
Mas o que vejo por aí são enums. Como ficaria a tabela de uma fita de vídeo:

public class Fita { enum Tipo { LANCAMENTO, NORMAL, PROMOCAO }; private Tipo tipo; private String titulo; // ? }

O Hibernate faria como a tabela disso?