DAO sem banco de dados e GUI

40 respostas
M

boa noite, estou com uma duvida

é possível o seguinte…

se trabalhar com o padrao DAO armazenando os dados em uma coleção?

não usando banco de dados e interface gráfica…

Obrigado

40 Respostas

wagnerfrancisco

Sim.

O padrão DAO abstrai o mecanismo de persistência, seja ele um banco de dados, um arquivo texto ou uma coleção em memória.

A ausência de interface gráfica no sistema também não interfere em nada no funcionamento do padrão.

M

wagnerfrancisco:
Sim.

O padrão DAO abstrai o mecanismo de persistência, seja ele um banco de dados, um arquivo texto ou uma coleção em memória.

A ausência de interface gráfica no sistema também não interfere em nada no funcionamento do padrão.

Bacana isso einh cara…

Mas teria alguma material ou exemplo para me dar?

Pois so acho se trabalhando com banco de dados

E ai nao sei como imaginar fazer a relacao entre DAO e colecao…

wagnerfrancisco

Eu não tenho nenhum exemplo pronto.

Mas tenta fazer algo, se tiver dúvidas posta aí. :smiley:

A princípio é simples, mais simples do que num banco de dados. Você armazena tudo numa coleção e percorre ela pra fazer as consultas…

M

wagnerfrancisco:
Eu não tenho nenhum exemplo pronto.

Mas tenta fazer algo, se tiver dúvidas posta aí. :smiley:

A princípio é simples, mais simples do que num banco de dados. Você armazena tudo numa coleção e percorre ela pra fazer as consultas…

é to vendo uma aula…

seria tipo

no controlador da classe vc faz a operacoes CRUD

no DAO da classe vc realmente faz a alteração no objeto

Mas aqui, eu devo criar o atributo coleção aonde?

Main? No DAO?

Aonde seria o local mais indicado?

Obrigado

A

Da uma procurada,
nesse site abaixo:

http://www.algaworks.com/treinamentos/apostilas

Tem muitas apostilas ai boas.

M

enfim fiz meu exemplo usando apenas um dado…

dei uma lida em algo aqui no forum e vi uma serie de aulas que um cara postou no youtube sobre DAO com MYSQL e GUI

e fiz assim

criei 4 packages no projeto

model - classe basica do telefone com get e set e atributo

vision - aonde tem as classes que interagem com o usuario (nao usei GUI neste caso, não sei como chamam pra interface que nã seja grafica)

control - classe controladora que faz a interação com usuario e DAO

persistence - coloquei a classe DAO aonde faz o CRUD com o map

exception - coloquei as classes de excecao que julguei que poderiam ocorrem no sistemas

mas não sei se implementei os metodos nos classes certinhas entende…

abaixo segue as classes

package model;

public class Telefone {

	private String telefone;

	public Telefone(String telefone) {
		this.telefone = telefone;
	}

	public String getTelefone() {
		return telefone;
	}

	public void setTelefone(String telefone) {
		this.telefone = telefone;
	}

	@Override
	public boolean equals(Object obj) {
		return ((Telefone) obj).getTelefone().equals(this.telefone);
	}
}
package control;

import model.Telefone;
import persistence.TelefoneDAO;
import exception.CodigoInvalidoException;
import exception.TelefoneDuplicadoException;

public class ControladorTelefone {

	private TelefoneDAO dao;

	public ControladorTelefone() {

		dao = new TelefoneDAO();
	}

	public void adicionar(String telefone) {

		if (telefoneExiste(telefone)) {
			throw new TelefoneDuplicadoException();
		}

		dao.adicionar(new Telefone(telefone));
	}

	public void editar(int codigo, String telefone) {

		if (telefoneExiste(telefone)) {
			throw new TelefoneDuplicadoException();
		}

		if (codigoNaoExiste(codigo)) {
			throw new CodigoInvalidoException();
		}

		dao.editar(codigo, new Telefone(telefone));
	}

	public void remover(int codigo) {

		if (codigoNaoExiste(codigo)) {
			throw new CodigoInvalidoException();
		}

		dao.remover(codigo);
	}

	public String listarTodos() {

		return dao.toString();
	}

	public Telefone procurar(int codigo) {

		if (dao.getTelefones().containsKey(codigo)) {
			return dao.getTelefones().get(codigo);
		} else {
			return null;
		}
	}

	public boolean listaTelefoneEstaVazia() {
		return dao.getTelefones().isEmpty();
	}

	private boolean telefoneExiste(String telefone) {

		return dao.getTelefones().containsValue(new Telefone(telefone));
	}

	private boolean codigoNaoExiste(int codigo) {

		return !dao.getTelefones().containsKey(codigo);
	}
}
package persistence;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import model.Telefone;

public class TelefoneDAO {

	private Map<Integer, Telefone> telefones;
	private int indice = 0;

	public Map<Integer, Telefone> getTelefones() {
		return telefones;
	}

	public TelefoneDAO() {
		telefones = new HashMap<>();
	}

	public void adicionar(Telefone telefone) {

		if (telefone == null) {
			throw new IllegalArgumentException("Telefone inválido");
		}

		telefones.put(new Integer(++indice), telefone);
	}

	public void editar(int codigo, Telefone telefone) {

		if (telefone == null) {
			throw new IllegalArgumentException("Telefone inválido");
		}

		telefones.put(Integer.valueOf(codigo), telefone);
	}

	public void remover(int codigo) {

		telefones.remove(Integer.valueOf(codigo));
	}

	@Override
	public String toString() {

		int contador = 1;
		Iterator<Telefone> it;
		StringBuilder listaTelefone = new StringBuilder();

		for (it = telefones.values().iterator(); it.hasNext(); contador++) {

			String telefone = it.next().getTelefone();

			listaTelefone.append(contador).append("-").append(telefone);

			if (it.hasNext()) {
				listaTelefone.append(" --- ");
			}
		}
		return listaTelefone.toString();
	}
}
package vision;

import java.util.Scanner;

import model.Telefone;
import control.ControladorTelefone;
import exception.CodigoInvalidoException;
import exception.TelefoneDuplicadoException;

public class IUTelefone {

	private Scanner input;
	private ControladorTelefone controladorTelefone;

	public IUTelefone() {
		input = new Scanner(System.in);
		controladorTelefone = new ControladorTelefone();
	}

	public void adicionarTelefone() {

		try {
			System.out.print("Digite o telefone: ");
			String telefone = input.next();

			controladorTelefone.adicionar(telefone);

		} catch (TelefoneDuplicadoException e) {
			e.printStackTrace();
		}
	}

	public void editarTelefone() {

		controladorTelefone.listarTodos();

		if (controladorTelefone.listaTelefoneEstaVazia()) {
			System.out.println("Lista de telefone(s) vazia");
		} else {

			try {

				System.out.println(controladorTelefone.listarTodos());

				System.out.print("Digite o codigo do telefone: ");
				int codigo = input.nextInt();

				System.out.print("Digite o novo numero do telefone: ");
				String telefone = input.next();

				controladorTelefone.editar(codigo, telefone);

			} catch (CodigoInvalidoException e) {
				e.printStackTrace();
			} catch (TelefoneDuplicadoException e) {
				e.printStackTrace();
			}
		}
	}

	public void excluirTelefone() {

		if (controladorTelefone.listaTelefoneEstaVazia()) {
			System.out.println("Lista de telefone(s) vazia");
		} else {
			try {

				System.out.println(controladorTelefone.listarTodos());

				System.out.print("Digite o codigo do telefone: ");
				int codigo = input.nextInt();

				controladorTelefone.remover(codigo);

			} catch (CodigoInvalidoException e) {
				e.printStackTrace();
			}
		}
	}

	public void listarTelefone() {

		if (controladorTelefone.listaTelefoneEstaVazia()) {
			System.out.println("Lista de telefone(s) vazia");
		} else {
			System.out.println(controladorTelefone.listarTodos());
		}
	}

	public void procurarTelefone() {

		System.out.print("Digite o codigo do telefone: ");
		int codigo = input.nextInt();

		Telefone telefone = controladorTelefone.procurar(codigo);
		if (telefone == null) {
			System.out.println("Telefone não encontrado");
		} else {
			System.out.println(telefone.getTelefone());
		}
	}
}

bom acima esta o codigo e gostaria de saber se coloquei as coisas no lugar correto

fiz esse codigo pra entender como funciona o DAO

e tipo depois que me ajudarem dizendo aonde ta errado

pretendo implementar interface no DAO

e depois criar uma agenda de contatos…usando isso

vlw

M

to dando um up no topico pq n estou conseguindo ver ele na lista de topicos

wagnerfrancisco

Que estranho, não recebi notificações por e-mail que este tópico foi respondido.

Eu acho que a estrutura que você está criando tá ficando boa. Algumas observações:

Um pacote chamado exception não é muito recomendável. A exceção deve estar próxima à classe que a disparou. Se o seu DAO disparou uma exceção, deixe ela no pacote onde os DAOs estão. Se foi o controller, deixe no controller… etc. Veja que nas próprias APIs do Java isto é comum.

Em relação ao seu DAO, você criou um Map pra armazenar os dados, mas indexou por meio de um inteiro. É o mesmo que usar um Set ou uma Lista. A princípio seria melhor usar um Set mesmo.

Na classe telefone, não há garantias que o atributo telefone não vai ser nulo. Se ele for nulo, você vai receber uma NullPointerException quando tentar usar o equals. Aliás, sempre que sobrescrever o equals, sobrescreva o método hashCode também. O correto é você fazer uma consistência no seu construtor, não deixar criar um telefone nulo. Outra abordagem seria criar uma classe que valida o telefone e invocar ela antes de persistir. Neste caso, eu acho mais recomendável a primeira opção.

A lógica de procurar, no seu controlador, pode ser passada para o DAO. O Controller pode só delegar isto para o DAO (e ele já traz somente o telefone necessário). Imagine que, se você estivesse usando um banco de dados, não ia querer trazer todos os dados do banco e depois comparar todos os elementos no seu controller. Você faria uma consulta trazendo apenas o resultado que quer (se houver).

Alguns outros detalhes adicionais (talvez pra vc pensar se sua aplicação ficar mais complexa):

  1. Hoje você tem apenas um tipo de dado para persistir. Uma aplicação normalmente tem muitas entidades e, as vezes, você precisa persistir várias delas ao mesmo tempo. Caso dê falha ao persistir uma, você deve abortar a persistência das outras e voltar ao estado anterior, ou seja, fazer um controle de transação. Mas com vários tipos de dado, você vai ter vários DAO. Onde fica este controle? Aplicações normalmente tem serviços que garantem isso. Um serviço pode ter acesso a mais de um dao e garante o controle transacional.

  2. É comum dividir os pacotes de acordo com camadas, e não de acordo com o MVC. No seu caso, você misturou. Tem um pacote de persistência e tem pacote pra model, view e controller. O problema é que, se você tiver lógicas mais complexas, ou mesmo serviços como citei acima, eles não tem onde ficar neste exemplo (por isso que eu digo que estes detalhes servem pra quando sua app crescer).

M

ta estranho o forum, eu abro a pagina 1 e so vejo alguns topicos…

tamo tentando vlw…

como que eu vejo isso na API?

Olha mudei pra Set, mas vou te fala a verdade meu plano era usar com chaves e hashmap…

Pq poderia usar 2 tipos de localizar, via codigo e telefone(String)

E principalmente usar o get(); e o editar ficar mais facil…

Mas lançar excecao que nao adicionou pq ja existe seria mais facil pelo Set

Eu deveria fazer o controle de null na classe modelo então no construtor do objeto telefone?

Como que sobescrevo o hashcode, eu sei que o eclipse gera ele se eu pedir mas queria saber qual uma forma mais interessante…

Tipo é realmente bem mongol,

Banco de dados, traz tudo pra mim que a aplicacao vai filtrar…

Tenho que deixar isso para a query né?

Problema e saber me posicionar aonde devo colocar os metodos em qual classe…

Cara ficou um pouco dificil de entender o que vc quiz dizer, como te disse primeira vez q to fazendo isso sabe, mei osso ter essa visão…

Mas é pq é o seguinte, tenho um exercicio da faculdad de fazer uma agenda…

Certa vez coloquei o codigo e me sugeriram estudar DAO e EJB…mei pesado pra quem mau ta sabendo OO

5 meses que to no Java

Mas uma das minha dificuldades reflete no q vc disse la em cima sobre aonde colocar as classes de excecao…

Pq meu professor falou que eu deveria colocar classes de excecao no pacote controle

Ai fico to mei sem noção de como posicionar minhas classes nos pacotes…

Mas valeu pela ajuda cara

Obrigado

wagnerfrancisco

É só analisar exceções comuns, em geral elas não estão num pacote específico de exceções. Por exemplo NullPointerException e IllegalArgumentException estão no pacote java.lang. SQLException está no pacote java.sql, e assim vai.

Particularmente eu não gosto de usar essa abordagem do Map por que você tá gerando um id que é dependente do DAO (e espalhando este id pelo restante da aplicação). Imagine que você tivesse que mudar o mecanismo de persistência para uma base de dados, pra onde iria esse id? Se você precisa de um identificador extra, o teu telefone poderia ter uma propriedade id. Aí você pode até usar o Map pra indexar por ele. Mas não é regra, eu acho que até já vi em algum framework algo assim, um id que não faz parte do objeto. Entretanto, se for pra manter do jeito atual, acho que você poderia usar uma Lista, que já é indexada naturalmente. :slight_smile:

Sim, você pode checar por null tanto no construtor Telefone, quanto no método setTelefone (se você realmente precisa dele). Aí você garante que teu objeto sempre estará num estado válido e não precisa ficar fazendo checagens em outro lugar (estude sobre invariante da classe, se quiser saber mais). No caso do hashCode, a regra é que sempre que você sobrescrever o equals, deve sobrescrever o hashCode. Pra dois objetos iguais, o hashCode deve ser igual. Preferencialmente, para objetos diferentes o hashCode deve ser diferente (mas não é regra). Como você só tem uma propriedade na sua classe (telefone), você pode simplesmente retornar o hashCode desta propriedade, que já garante o que eu falei:

@Override
public int hashCode() {
   return telefone.hashCode();
}

Quando você tem mais de um atributo, existe um cálculo matemático que é utilizado. É o que o eclipse usa. Outra maneira é usar a class HashCodeBuilder da biblioteca apache commons lang (eu acho até melhor).

Isso, sua query poderia filtrar pelo id já. No teu caso é só fazer aquela busca dentro do DAO.

Vai com calma. O padrão DAO é até tranquilo, mas eu não me preocuparia em entender EJB tão cedo. Domine bem a linguagem antes e aprofunde os conceitos em OO, se não vc nem vai saber pq está usando EJB.

macario1983:

Mas uma das minha dificuldades reflete no q vc disse la em cima sobre aonde colocar as classes de excecao…

Pq meu professor falou que eu deveria colocar classes de excecao no pacote controle

Ai fico to mei sem noção de como posicionar minhas classes nos pacotes…

Mas valeu pela ajuda cara

Obrigado

Se a exceção for gerada por algum controlador, sim.

No que eu puder lhe ajudar, estou aqui… :smiley:

M

[quote=wagnerfrancisco]

macario1983:

como que eu vejo isso na API?

Cara até outro dia o Sergio Taborda me deu umas dicas mas ainda to com dificuldade sobre gerar excecoes por causa dos conceitos…

Sobre checked e unchecked exception…

Mas isso fica para depois…

kkkkk isso ja ta me deixando confuso…

Eu entendo que vc quiz dizer q se eu quiser trabalhar com campo id eu tenho que criar este atributo na classe model…correto?

Se for sim, uma vez li num livro ou internet recomendando na se criar um campo id no model…

eu achei um slide falando hashcode, seria tipo um DNA dos objetos…

Objetos iguais tem o msm hashcode correto?

Vc disse pra eu sobescrever o metodo, usando ja o proprio metodo igual no exemplo, ele não faz isso sozim?

Vou fazer isso…

Obrigado

wagnerfrancisco

A exceção checada você é obrigado a tratar. Normalmente aplicações relativas ao domínio da aplicação são checadas (você realmente deve tratá-las). Um exemplo simples: uma aplicação bancária que tem a opção de saque. Você pode ter uma exceção SaldoInsuficienteException, e esta exceção possivelmente será checada, por que você realmente pode e deve tratá-la de alguma maneira.

Exceções que vem de um DAO, em contrapartida, muitas vezes são unchecked. Não há muito que se fazer caso um erro ocorra, em geral ela é disparada e tratada de maneira genérica informando que um erro ocorreu.

Mas isso não é regra, tem gente que gosta de deixar todas as exceções como unchecked. Os próprios frameworks mudam isto entre versões… se não estou enganado, o Hibernate no passado gerava exceções checadas, e hoje lança exceções não checadas.

Quanto ao hashCode, é preciso entender o seguinte. Quando você cria um objeto novo, ele sempre vai ter um identificador que o diferencia de outro objeto, ele vai ser único. Quando você compara objetos com ==, é este identificador que é utilizado na comparação. Se você não sobrescreve o equals, ele também se baseia neste identificador (compara a referência). Mas se você sobrescrever o equals, ele não vai mais utilizar este identificador. O critério de igualdade é você quem vai definir. E, a partir daí, o seu hashCode deve ser sobrescrito pra refletir o seu novo equals. Entenda como uma regra, sempre que sobrescrever o equals, sobrescreva o hashCode. Ele é utilizado em coleções (Set, Maps, etc.). Se você não escrever o hashCode e usar o objeto numa coleção, você pode ter problemas de não conseguir buscar o objeto de novo. Além disso, um hashCode mal escrito pode reduzir o desempenho da coleção (pq esse código é usado pra espalhar os objetos dentro da coleção).

M

wagnerfrancisco:
A exceção checada você é obrigado a tratar. Normalmente aplicações relativas ao domínio da aplicação são checadas (você realmente deve tratá-las). Um exemplo simples: uma aplicação bancária que tem a opção de saque. Você pode ter uma exceção SaldoInsuficienteException, e esta exceção possivelmente será checada, por que você realmente pode e deve tratá-la de alguma maneira.

Exceções que vem de um DAO, em contrapartida, muitas vezes são unchecked. Não há muito que se fazer caso um erro ocorra, em geral ela é disparada e tratada de maneira genérica informando que um erro ocorreu.

Mas isso não é regra, tem gente que gosta de deixar todas as exceções como unchecked. Os próprios frameworks mudam isto entre versões… se não estou enganado, o Hibernate no passado gerava exceções checadas, e hoje lança exceções não checadas.

Quanto ao hashCode, é preciso entender o seguinte. Quando você cria um objeto novo, ele sempre vai ter um identificador que o diferencia de outro objeto, ele vai ser único. Quando você compara objetos com ==, é este identificador que é utilizado na comparação. Se você não sobrescreve o equals, ele também se baseia neste identificador (compara a referência). Mas se você sobrescrever o equals, ele não vai mais utilizar este identificador. O critério de igualdade é você quem vai definir. E, a partir daí, o seu hashCode deve ser sobrescrito pra refletir o seu novo equals. Entenda como uma regra, sempre que sobrescrever o equals, sobrescreva o hashCode. Ele é utilizado em coleções (Set, Maps, etc.). Se você não escrever o hashCode e usar o objeto numa coleção, você pode ter problemas de não conseguir buscar o objeto de novo. Além disso, um hashCode mal escrito pode reduzir o desempenho da coleção (pq esse código é usado pra espalhar os objetos dentro da coleção).

ok, vc so nao respondeu quanto a questao da chave…hashmap…

campo id…

vlw

wagnerfrancisco

O que você deve ter lido é que o id normalmente é um aspecto de implementação, por isso você não deveria “poluir” suas entidades e as camadas mais altas da sua aplicação com ele.

Veja que o seu id está espalhado pelo sistema de qualquer maneira (as camadas superiores conhecem e utilizam o id). Aliás, de certo modo, o id no seu caso faz parte do domínio. O usuário do seu sistema referencia um telefone pelo id. Isso acontece muito em sistemas reais também (os usuários decoram ids pra referenciar as entidades rapidamente). O id acaba sendo utilizado fora da camada de persistência e faz parte da entidade.

Mesmo que esta não fosse a situação (o usuário não usa o id), você normalmente precisa associar o id à entidade para persistir num banco de dados.

Enfim, por tudo isso recomendo colocar o id na própria entidade. O que, repito, não impede você de usar um map pra indexar as entidades no DAO também.

M

wagnerfrancisco:
O que você deve ter lido é que o id normalmente é um aspecto de implementação, por isso você não deveria “poluir” suas entidades e as camadas mais altas da sua aplicação com ele.

Veja que o seu id está espalhado pelo sistema de qualquer maneira (as camadas superiores conhecem e utilizam o id). Aliás, de certo modo, o id no seu caso faz parte do domínio. O usuário do seu sistema referencia um telefone pelo id. Isso acontece muito em sistemas reais também (os usuários decoram ids pra referenciar as entidades rapidamente). O id acaba sendo utilizado fora da camada de persistência e faz parte da entidade.

Mesmo que esta não fosse a situação (o usuário não usa o id), você normalmente precisa associar o id à entidade para persistir num banco de dados.

Enfim, por tudo isso recomendo colocar o id na própria entidade. O que, repito, não impede você de usar um map pra indexar as entidades no DAO também.

Bom vamos por partes…

Não entendi muito bem certas coisas, mas tipo

Vc recomendou então eu usar um campo ID na classe modelo do telefone…

Ai venho uma duvida, como vou gerar as keys?

Ou melhor em qual lugar?

Pq eu posso pegar o tamanho do map + 1 e sera a key do novo telefone

Aqui você quiz dizer que eu poderia deixar como estava?

Ow eu deveria declarar o map<Integer, Telefone> e no campo chave eu iria usar no caso o campo id que esta na entidade telefone

Traduzindo…

Eu iria fazer igual numa tabela de banco de dados

long id
String telefone

Isso?

Obrigado

wagnerfrancisco

Você vai armazenar os telefones em uma coleção, que pode ser um map. Quanto a pegar o tamanho do map pra gerar o próximo id, acho que não seria correto. Se você inserir 3 elementos (ids 0, 1 e 2) e remover os elementos 0 e 1, o map fica com tamanho 1, e o próximo id seria 2, que já existe. A sua implementação com o índice era mais correta neste sentido.

O Map pode ser a coleção usada no DAO, mas o id ainda seria interessante na entidade - como no banco de dados.

Na primeira leitura que eu fiz do seu código, não tinha sacado o esquema do indice e do map. Você não reduz o índice quando remove um elemento. O índice nem sempre é o tamanho do map. Neste caso é interessante usar o Map mesmo.

M

wagnerfrancisco:
Você vai armazenar os telefones em uma coleção, que pode ser um map. Quanto a pegar o tamanho do map pra gerar o próximo id, acho que não seria correto. Se você inserir 3 elementos (ids 0, 1 e 2) e remover os elementos 0 e 1, o map fica com tamanho 1, e o próximo id seria 2, que já existe. A sua implementação com o índice era mais correta neste sentido.

O Map pode ser a coleção usada no DAO, mas o id ainda seria interessante na entidade - como no banco de dados.

Na primeira leitura que eu fiz do seu código, não tinha sacado o esquema do indice e do map. Você não reduz o índice quando remove um elemento. O índice nem sempre é o tamanho do map. Neste caso é interessante usar o Map mesmo.

Eu havia citado acima que iria pegar o size()+1;

Mas isso fica pra amanha…

Irei trabalhar e melhorar nas questoes…

VLw

wagnerfrancisco

Mas é isso que eu digo, o size não é confiável. Veja o meu post anterior novamente.

M

e ae cara blz?

public static void mostrar(Map<Integer, String> mapa) {

		for (int i = 1; i <= 10; i++) {
			System.out.println("Proxima chave: " + (mapa.size() + 1));
			mapa.put((mapa.size() + 1), String.valueOf((mapa.size() + 1)));
			System.out.println(mapa.values().toString());
		}
	}

era isso que eu estva lhe falando

mas vc tem razão, depois que fiz o codigo eu percebi o seguinte…

a critica que se pode ter e q vc fez e eu axo q é kkkk

é q se meu objetivo é simular no map um banco estaria errado…

se eu tenho 10 registros, o ultimo tem chave 10

entao eu deleto 8 e fico com total 2, quando eu chegar no 10 vai dar conflito, eu poderia tratar isso dando um incremento na chave ate q se resolvesse…sim

e seria errado

o que tive em mente, pegar a ultima chave do map…e somar mais 1…

ficaria menos pior apesar que acho que manter o campo id no DAO seja melhor…

pq ele seria o controle daquele map…

tipo posso fazer o que for que sempre estara igula a um auto incremente de um banco de dados…

e ae q tu achas?

wagnerfrancisco

É isso aí. Ou você pega o último elemento do map, ou usa aquela variável índice no DAO e não decrementa ela quando remove um objeto (o que é melhor, pq se deletar o último elemento ele não vai repetir o id também).

M

cara me surgiu um problema ao verificar se existe um telefone no map…

a classe telefone ta assim

package model;

public class Telefone {

	private String telefone;

	public Telefone(String telefone) {

		if (telefone == null) {
			throw new IllegalArgumentException("Telefone inválido");
		}

		this.telefone = telefone;
	}

	public String getTelefone() {
		return telefone;
	}

	public void setTelefone(String telefone) {
		this.telefone = telefone;
	}

	@Override
	public boolean equals(Object obj) {

		return (obj instanceof Telefone)
				&& (((Telefone) obj).telefone == this.telefone);
	}

	@Override
	public int hashCode() {
		return hashCode();
	}

}

e no controlador eu verifico se ja existe aquele telefone…

usando o metodo containsValue ou value().contais();

e não acha quando eu insiro 2 vezes o mesmo telefone…

private boolean telefoneExiste(String telefone) {

		return dao.getTelefones().containsValue(new Telefone(telefone));
	}
private boolean telefoneExiste(String telefone) {

		return dao.getTelefones().containsValue(telefone);
	}

eu faço das 2 formas e não certo…pq?

wagnerfrancisco

Aparentemente tem dois problemas. O primeiro é no seu método equals, você está utilizando == para comparar as strings. Utilize equals.

O segundo é que o seu hashCode deve retornar o hashCode da string: this.telefone.hashCode().

M

wagnerfrancisco:
Aparentemente tem dois problemas. O primeiro é no seu método equals, você está utilizando == para comparar as strings. Utilize equals.

O segundo é que o seu hashCode deve retornar o hashCode da string: this.telefone.hashCode().

que vergonha…eu pensava que no caso equals eu n precisaria mais usar ele

eu até baixei um pdf muito bom cara…

e falava la sobre o equals e hashcode

e questao de comparações…

mas ai vem uma coisa, e caso eu tenha uma classe com 3 atributos…

como q ficaria a classe hash e equals?

deu certo…vlw

wagnerfrancisco

Todos os atributos que você utiliza para comparar no equals, deve usar no hashCode. Por isso que o eclipse faz aquele cálculo, o objetivo é usar todos os teus atributos e sempre gerar um código diferente para atributos diferentes.

Se tu tiver mais atributos no objeto, e eles puderem ser nulos, vai ter que checar se eles são ou não nulos antes de comparar. :stuck_out_tongue:

M

entre as terminei…

agora eu reduzi pra 3 package

classe controller

package controller;

import model.Telefone;
import model.TelefoneDAO;

public class ControladorTelefone {

	private TelefoneDAO dao;

	public ControladorTelefone() {

		dao = new TelefoneDAO();
	}

	public void adicionar(String telefone) {

		if (telefoneExiste(telefone)) {
			throw new TelefoneDuplicadoException();
		}

		dao.adicionar(new Telefone(telefone));
	}

	public void editar(int codigo, String telefone) {

		if (telefoneExiste(telefone)) {
			throw new TelefoneDuplicadoException();
		}

		dao.editar(codigo, new Telefone(telefone));
	}

	public void remover(int codigo) {

		dao.remover(codigo);
	}

	public String listarTodos() {

		return dao.toString();
	}

	public String procurarTelefone(String telefone) {
		return dao.procurarTelefone(new Telefone(telefone)).getTelefone();
	}

	public String procurarCodigo(int codigo) {
		return dao.procurarCodigo(codigo).toString();
	}

	public boolean listaTelefoneEstaVazia() {

		return dao.getTelefones().isEmpty();
	}

	private boolean telefoneExiste(String telefone) {

		return dao.getTelefones().containsValue(new Telefone(telefone));
	}

}

classe model

package model;

public class Telefone {

	private String telefone;

	public Telefone(String telefone) {

		if (telefone == null) {
			throw new IllegalArgumentException("Telefone inválido");
		}

		this.telefone = telefone;
	}

	public String getTelefone() {
		return telefone;
	}

	public void setTelefone(String telefone) {
		this.telefone = telefone;
	}

	@Override
	public boolean equals(Object obj) {

		return (obj instanceof Telefone)
				&& (((Telefone) obj).telefone.equals(this.telefone));
	}

	@Override
	public int hashCode() {
		return telefone.hashCode();
	}

}

classe DAO

package model;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;


public class TelefoneDAO {

	private Map<Integer, Telefone> telefones;
	private int indice = 0;

	public Map<Integer, Telefone> getTelefones() {
		return telefones;
	}

	public TelefoneDAO() {
		telefones = new HashMap<>();
	}

	public void adicionar(Telefone telefone) {

		telefones.put(new Integer(++indice), telefone);
	}

	public void editar(int codigo, Telefone telefone) {

		telefones.put(Integer.valueOf(codigo), telefone);
	}

	public void remover(int codigo) {

		telefones.remove(Integer.valueOf(codigo));
	}

	public Telefone procurarTelefone(Telefone telefoneProcurado) {

		for (Telefone telefoneLista : telefones.values()) {
			if (telefoneProcurado.equals(telefoneLista)) {
				return telefoneLista;
			}
		}
		throw new IllegalArgumentException("Telefone não encontrado");
	}

	public String procurarCodigo(int codigo) {
		return telefones.get(codigo).getTelefone();
	}

	@Override
	public String toString() {

		Iterator<Telefone> it;
		StringBuilder listaTelefone = new StringBuilder();

		for (it = telefones.values().iterator(); it.hasNext();) {

			String telefone = it.next().getTelefone();

			listaTelefone.append(1).append("-").append(telefone);

			if (it.hasNext()) {
				listaTelefone.append(" --- ");
			}
		}
		return listaTelefone.toString();
	}
}

oq precisa ser melhorado e implementado?

M

alguem???

wagnerfrancisco

Você deve garantir a invariante do tipo no método setTelefone também. Não adianta checar por nulo só no construtor, se depois um usuário pode fazer isto: telefone.setTelefone(null).

A implementação telefoneExiste deveria estar dentro do dao.

M

wagnerfrancisco:
Você deve garantir a invariante do tipo no método setTelefone também. Não adianta checar por nulo só no construtor, se depois um usuário pode fazer isto: telefone.setTelefone(null).

A implementação telefoneExiste deveria estar dentro do dao.

Cara desculpe a demora em responder mas precisei me dedicar a estudar mais php para um teste…

Mas voltando ao nosso assunto DAO com coleções me diga algo, eu somente preciso fazer essas 2 alterações para eu ter um DAO autentico?

Caso a resposta seja sim…

Ai vem a parte 2 do meu plano…

Fazer uma agenda de contatos com telefones…

E ai como ficaria minha relacao 1 para n

1 contato tem n telefones…

Vlw

wagnerfrancisco

macario1983:
wagnerfrancisco:
Você deve garantir a invariante do tipo no método setTelefone também. Não adianta checar por nulo só no construtor, se depois um usuário pode fazer isto: telefone.setTelefone(null).

A implementação telefoneExiste deveria estar dentro do dao.

Cara desculpe a demora em responder mas precisei me dedicar a estudar mais php para um teste…

Mas voltando ao nosso assunto DAO com coleções me diga algo, eu somente preciso fazer essas 2 alterações para eu ter um DAO autentico?

Independente de usar DAO ou não, se você quer garantir que o teu objeto fique num estado consistente, deve checar por nulo no método set também. Uma grande parte dos sistemas não faz este tipo de consistência diretamente na entidade, normalmente só delega para um objeto validador. Mas no caso, o DAO não tem nada a ver.

Quanto à segunda alteração, bem, imagine que você precise do método telefoneExiste em outros controladores (isto é comum), teria que replicar a lógica em diversos pontos da aplicação. Isto pq vc está tirando uma responsabilidade do DAO e jogando no controller.

macario1983:

Caso a resposta seja sim…

Ai vem a parte 2 do meu plano…

Fazer uma agenda de contatos com telefones…

E ai como ficaria minha relacao 1 para n

1 contato tem n telefones…

Vlw

Num banco de dados, usando jdbc direto, vc tem algumas possibilidades, por exemplo:

  • Ao buscar o contato, já carregar os telefones.
  • Só trazer os identificadores dos telefones no contato e, quando necessário, passar o identificador para o TelefoneDAO carregar o objeto.
  • Usar algum mecanismo de lazy loading

Mas no seu caso, é tudo em memória. Você pode armazenar o telefone e manter a referência no contato. Quando buscar o contato, as referências do telefone já estarão nele. Você não tem o problema de ter que reconstruir o objeto a partir dos dados, coisa comum num bd relacional.

M

wagnerfrancisco:
macario1983:
wagnerfrancisco:
Você deve garantir a invariante do tipo no método setTelefone também. Não adianta checar por nulo só no construtor, se depois um usuário pode fazer isto: telefone.setTelefone(null).

A implementação telefoneExiste deveria estar dentro do dao.

Cara desculpe a demora em responder mas precisei me dedicar a estudar mais php para um teste…

Mas voltando ao nosso assunto DAO com coleções me diga algo, eu somente preciso fazer essas 2 alterações para eu ter um DAO autentico?

Cara vou colocar entao o metodo set no construtor…acho que vai ficar mais simples…

oq achas?

macario1983:

Caso a resposta seja sim…

Ai vem a parte 2 do meu plano…

Fazer uma agenda de contatos com telefones…

E ai como ficaria minha relacao 1 para n

1 contato tem n telefones…

Vlw

Num banco de dados, usando jdbc direto, vc tem algumas possibilidades, por exemplo:

  • Ao buscar o contato, já carregar os telefones.
  • Só trazer os identificadores dos telefones no contato e, quando necessário, passar o identificador para o TelefoneDAO carregar o objeto.
  • Usar algum mecanismo de lazy loading

Mas no seu caso, é tudo em memória. Você pode armazenar o telefone e manter a referência no contato. Quando buscar o contato, as referências do telefone já estarão nele. Você não tem o problema de ter que reconstruir o objeto a partir dos dados, coisa comum num bd relacional.

Cara so 1 duvida quando eu tentar fzer isso via banco

Quando criamos um tabela deste tipo

Seria

tabela telefone - id - telefone
tabela contato - id - nome - email - fk_telefone…

Seria isso tb pro model da classe?

Obrigado

wagnerfrancisco

Acredito que num banco você armazenaria o id do contato na tabela telefone. Assim, se precisar ter muitos telefones por contato, não há problema. Entretanto 1 telefone não pode ter muitos contatos. Como você mencionou que é 1 pra n de contato pra telefone, não há problemas.

Em objetos, independente de banco x ou y, você faz esta associação:

class Contato {
   Integer id;
   List<Telefone> telefones;

   //...
}

class Telefone {
   String id;

   //...
}
M
wagnerfrancisco:
Acredito que num banco você armazenaria o id do contato na tabela telefone. Assim, se precisar ter muitos telefones por contato, não há problema. Entretanto 1 telefone não pode ter muitos contatos. Como você mencionou que é 1 pra n de contato pra telefone, não há problemas.

Em objetos, independente de banco x ou y, você faz esta associação:

class Contato {
   Integer id;
   List<Telefone> telefones;

   //...
}

class Telefone {
   String id;

   //...
}

verdade cara...vc esta certo...

irei trabalha no remapeamento...mas vc n respondeu quanto a eu colocar set na classe construturo

wagnerfrancisco
macario1983:
wagnerfrancisco:
Acredito que num banco você armazenaria o id do contato na tabela telefone. Assim, se precisar ter muitos telefones por contato, não há problema. Entretanto 1 telefone não pode ter muitos contatos. Como você mencionou que é 1 pra n de contato pra telefone, não há problemas.

Em objetos, independente de banco x ou y, você faz esta associação:

class Contato {
   Integer id;
   List<Telefone> telefones;

   //...
}

class Telefone {
   String id;

   //...
}

verdade cara...vc esta certo...

irei trabalha no remapeamento...mas vc n respondeu quanto a eu colocar set na classe construturo

Como assim? Não entendi esta última parte...

M
wagnerfrancisco:
macario1983:
wagnerfrancisco:
Acredito que num banco você armazenaria o id do contato na tabela telefone. Assim, se precisar ter muitos telefones por contato, não há problema. Entretanto 1 telefone não pode ter muitos contatos. Como você mencionou que é 1 pra n de contato pra telefone, não há problemas.

Em objetos, independente de banco x ou y, você faz esta associação:

class Contato {
   Integer id;
   List<Telefone> telefones;

   //...
}

class Telefone {
   String id;

   //...
}

verdade cara...vc esta certo...

irei trabalha no remapeamento...mas vc n respondeu quanto a eu colocar set na classe construturo

Como assim? Não entendi esta última parte...

Vc me disse...

Verifique tb no setTelefone() se o usuario esta passando null

E ai eu lhe disse, entao para simplificar...

Irei usar o setTelefone no construtor da classe pois ai eu verifico se esta null somente no setTelefone();

wagnerfrancisco

Existe um problema com isso, no caso de você ter uma classe que herda de Telefone e ela sobrescrever métodos de Telefone. Sugiro que leia este tópico:

Os últimos posts do ViniGodoy.

M

wagnerfrancisco:
Existe um problema com isso, no caso de você ter uma classe que herda de Telefone e ela sobrescrever métodos de Telefone. Sugiro que leia este tópico:

Os últimos posts do ViniGodoy.

eu vi aki…

vlw pela ideia

M

Cara desculpa a demora intensa em responder esse topico mas caso possa me ajudar ou outra pessoa

queria saber o seguinte, ja foi discutido pra mim nao ficou claro

num programa, aonde é uma agenda…

eu criei 3 classes modelo

pessoa
endereço
telefone

eu queria saber o seguinte, se eu devo colocar dentro da classe pessoa, a classe endereço e telefone?

lembrando que tem 1 endereço e n telefones…

se não, como fazer?

obrigado

wagnerfrancisco

Pode colocar. A classe Pessoa pode ter uma referência à Endereco e à uma coleção de Telefone (tal como List ou Set).

Neste caso, provavelmente, não faz sentido, mas Endereço poderia ter uma referência à Pessoa (se fosse uma relação um pra um). A questão aqui é se tu vai ou não usar relacionamentos bidirecionais (normalmente isto deve ser evitado). Veja aqui:

M

wagnerfrancisco:
Pode colocar. A classe Pessoa pode ter uma referência à Endereco e à uma coleção de Telefone (tal como List ou Set).

Neste caso, provavelmente, não faz sentido, mas Endereço poderia ter uma referência à Pessoa (se fosse uma relação um pra um). A questão aqui é se tu vai ou não usar relacionamentos bidirecionais (normalmente isto deve ser evitado). Veja aqui:

dei uma lida mas acho que nao entendi muito bem…

Tipo porque no exercicio anterior da professora, ela tinha pedido para criar a classe pessoa e endereco

Dentro da classe endereco contem campos, do tipo, rua, numero, cidade e cep…

Para nao criar uma classe muito extensa pessoa eu acredito que sugeriu isso…

Mas e o DAO? e Controlador?

Obrigaod

wagnerfrancisco

macario1983:
wagnerfrancisco:
Pode colocar. A classe Pessoa pode ter uma referência à Endereco e à uma coleção de Telefone (tal como List ou Set).

Neste caso, provavelmente, não faz sentido, mas Endereço poderia ter uma referência à Pessoa (se fosse uma relação um pra um). A questão aqui é se tu vai ou não usar relacionamentos bidirecionais (normalmente isto deve ser evitado). Veja aqui:

dei uma lida mas acho que nao entendi muito bem…

Tipo porque no exercicio anterior da professora, ela tinha pedido para criar a classe pessoa e endereco

Dentro da classe endereco contem campos, do tipo, rua, numero, cidade e cep…

Para nao criar uma classe muito extensa pessoa eu acredito que sugeriu isso…

Mas e o DAO? e Controlador?

Obrigaod

Mas você pode fazer isto. Crie a classe Pessoa e referencie Endereco nela.

No caso do DAO, eu faço o seguinte. Se Endereco for uma entidade separada, que você pode alterar ela independemente de alterar a classe Pessoa, eu crio um DAO específico pra ela. Mas se sempre que tu precisar alterar o Endereco, tiver que buscar a Pessoa e alterar através dela (parece o caso), eu faço tudo no DAO Pessoa.

No caso do controlador, depende mais da maneira que tu constrói a interface, da interação entre ela e o restante da sua app. Se você tem um formulário e nele vai salvar tanto a Pessoa quanto o Endereço, vc provavelmente vai ter apenas um controlador, que atende a esta requisição.

Criado 24 de julho de 2012
Ultima resposta 7 de out. de 2012
Respostas 40
Participantes 3