Dúvida em relacionamento um para muitos

Olá pessoal, sou novo aqui no fórum, por isso não sei se estou na sessão correta. Considerando que sim, aí vai a minha dúvida:

Eu preciso modelar duas classes, Time e Jogador. Onde um time possui vários jogadores e também um capitão. Um jogador só pode estar em um time. No banco de dados fica assim:

Agora no diagrama de classes eu estou em dúvida entre as seguintes opções (se é que tem alguma correta):

Unirelacional

Birelacional

Se houver alguma outra opção por favor me informem, pois ainda estou fraquinho em modelagem de objetos.

Grato.

Creio que seja Birelacional, ambos tem relação, o Time não existe sem jogadores, e os jogadores devem possuir um TIME.

Boa tarde a todos.

Eu faria isso de modo Unirelacional mudando a estrutura do Banco, onde colocaria o atributo “capitao” na tabela “jogador” como sendo do tipo booleano, ficando até mais fácil fazer o relacionamento nas tabelas de um pra muitos.

Um abraço.

Mais o atributo capitão ficaria dependente do Jogador? Time?

Um time tem 1 capitão, e um jogador é capitão.

Não entendi a lógica, a Tabela ficaria normalizada?

Eu criaria uma tabela independente de capitão, ID, NOME, TIME(ID_TIME ou NOME TIME).

[quote=mateuscs]Mais o atributo capitão ficaria dependente do Jogador? Time?

Um time tem 1 capitão, e um jogador é capitão.

Não entendi a lógica, a Tabela ficaria normalizada?

Eu criaria uma tabela independente de capitão, ID, NOME, TIME(ID_TIME ou NOME TIME).
[/quote]

Boa tarde a todos.

Mateuscs.

Não precisaria criar a tabela capitão.

A Lógica consiste na seguinte análise:

1º) Um time tem vários jogadores, porém um único jogador só poderá estar em um único time, logo o relacionamento obrigatório terá que ser de um (time) para muitos (jogadores). Neste caso, o ideal a fazer é isolar os atributos em cada tabela que tem referencial entre si, e no caso o atributo capitão esta relacionado ao jogador e não ao time, o único atributo que deverá estar nas duas tabelas, é o que identifica o relacionamento PK-FK, no caso os IDs.

2º) Esta reforça a minha primeira análise, onde se um time tem vários jogadores, e o capitão é apenas um jogador, mesmo que seja um só, contudo ele é um jogador, logo esse atributo tem que ficar onde :?: Na tabela jogador obviamente. Ainda assim, se este jogador mudar de time, ou deixar de ser o capitão do time e passar a braçadeira para outro jogador, e ai é que vem a pergunta crucial, como seria mudado o id_capitao da tabela time :?: :?: :?: Já imaginou a lógica de implementação a ser feita neste caso :roll:

Fico aqui imaginando o exemplo:

No primeiro caso voce teria que usar duas instruções “Update” do SQL", enquanto que no segundo caso, apenas uma instrução “Update”.

Veja o quão simples ficaria a lógica da sua implementação.

Ao fazer a diagramação estrutura do banco de dados, tem que ser levada em consideração de como se dará a entrada de dados do mesmo, e isto está relaciona com a lógica de sua implementação que fará parte da diagramação da lógica da aplicação (UML), e quanto mais simples voce fizer esta lógica, melhor ficará o desempenho de sua aplicação.

Quando for selecionar o capitão de um time basta fazer a junção das duas tabelas em uma instrução SQL com um “INNER JOIN”, onde o se fornecer o id_time como critério de seleção, voce trará todos os dados do time e seus jogadores, cujo o único capitão estará entre eles com o seu atributo booleano capitao setado para true.

Simples não :idea: :wink: :lol: :smiley: 8)

Olá senhores, muito obrigado por responderem.

discorpio, se eu colocasse o atributo capitão na tabela jogador, acredito que ia ficar difícil garantir que apenas um jogador fosse o capitão da equipe. Imagine a seguinte situação:

jogador A e jogador B jogam no vasco. O que me impede de marcar o atributo capitão como true nos dois jogadores?

No caso de o jogador( usuário ) querer sair do time, ele terá que nomear outra jogador dessa equipe como líder, passando a ser um jogador normal desde então.
Supondo que a estrutura do banco continue a mesma, qual seria a melhor implementação do relacionamento entre as classes?

Abraços.

Desculpe, não me expressei bem.
O time tem vários jogadores, um desses jogadores é o capitão. A equipe tem um e somente um capitão.

Fica normalizada pois o capitão vem da própria tabela jogadores. Entendeu?

discorpio

Explicação bem clara.
Obrigado.

Fica a seu critério coutohs.
No meu caso creio que inicialmente iria criar uma tabela capitao para nao ter influencia nas outras dependende, assim coutohs disse, os outros jogadores, podem ser true como capitães também.

Boa tarde a todos.

Respondendo a primeira pergunta:

Simples, voce poderia fazer uma validação de dados criando uma [color=red]trigger (gatilho em português)[/color], no banco de dados. Como eu uso o banco PostgreSQL, o seu dialeto SQL funciona executando uma função, assim ficaria o dialeto SQL do Postgres para a trigger.

CREATE FUNCTION auditor_capitao() RETURNS trigger AS $audit_cap$
    BEGIN
        IF (NEW.capitao is null) THEN
            NEW.capitao = false;
        END IF;
        IF (NEW.capitao = true) THEN
            UPDATE jogador SET capitao = false WHERE fk_equipe = NEW.fk_equipe AND id_jogador <> NEW.id_jogador;
        END IF;
        RETURN NEW;
    END;
$audit_cap$ LANGUAGE plpgsql;

CREATE TRIGGER audit_cap AFTER INSERT OR UPDATE ON jogador
    FOR EACH ROW EXECUTE PROCEDURE auditor_capitao();

Repare que usei a opção [color=red] “AFTER INSERT OR UPDATE (Após Inserir ou Atualizar)”[/color], isto porque uma instrução [color=red]“UPDATE”[/color] está atualizando o mesmo banco onde a trigger está sendo disparada, e a condição momentânea “AFTER (Após)” só irá disparar a trigger novamente se as condições IFs foram verdadeiras, evitando assim o Loop Infinito.

Todos sabem que uma Trigger é o melhor caminho para validações de campos em banco de dados.

Respondendo a segunda pergunta.

Neste caso basta voce designar um capitão para o time que jogador está saindo apenas, e quando atualizar o jogador no time novo com o atributo capitão = true, a trigger acima se encarregará de atualizar o resto, é claro não necessariamente nesta ordem, ou seja, voce primeiro tem que colocar o jogador no time novo e depois designar um capitão no time antigo.

Respondendo a terceira pergunta.

Caso voce insista em manter o banco do jeito que está, nada te impede de fazer isto, e na implementação de classes o relacionamento pode ficar Unirelacional mesmo, eis que voce não precisa ter uma atributo do tipo Jogador na tabela Time ou Equipe, (escreve Equipe para não confudir com a classe Time do java.SQL.Time dentro do java, e dentro do banco, com o tipo de campo Time), eis que a inserção, bem como a atualização do atributo id_capitao na tabela Equipe ficará por conta da tabela Jogador, e neste caso voce pode também criar uma trigger dentro da tabela jogador, para atualizar este id_capitao na tabela time, assim:

CREATE FUNCTION auditor_capitao() RETURNS trigger AS $audit_cap$
    BEGIN
        IF (NEW.capitao is null) THEN
            NEW.capitao = false;
        END IF;
        IF (NEW.capitao = true) THEN
            UPDATE equipe SET id_capitao = New.id_jogador WHERE id_equipe = NEW.fk_equipe;
        END IF;
        RETURN NEW;
    END;
$audit_cap$ LANGUAGE plpgsql;

CREATE TRIGGER audit_cap BEFORE INSERT OR UPDATE ON jogador
    FOR EACH ROW EXECUTE PROCEDURE auditor_capitao();

Repare que agora a opção [color=red]“AFTER” mudou para “BEFORE”[/color], eis que ele está atualizando uma tabela diferente daquela que a trigger está sendo disparada.

Espero ter ajudado.
Um Abraço.

discorpio, muito obrigado pelas respostas. Elas resolveram a minha dúvida :slight_smile:

abraços.

a propósito, bem lembrado o lance da classe Time do java ehehehe. Eu nem lembrava disso.