Dúvida sobre DAO

Olá amigos do GUJ!

Estou com uma dúvida, e apesar de pesquisar tanto no ferramenta de busca quanto no google, não consegui nada achar esclarecendo o que eu queria. Vamos ver se alguém consegue esclarecer essa dúvida pra mim. :slight_smile:

Recentemente aprendi sobre DAO no meu curso, e algumas coisas não ficaram claras.
O contexto do problema: Tenho um objeto produto(int id, String nome, int estoque, double valor), um objeto venda(int id, Produto produto,int quantidade, double valor) e seus respectivos DAOs.
Para efeitos didáticos a venda possui somente um produto.

1ª Dúvida:
Quando eu uso o método selectById(int id) do DAO venda, ela já me traz um objeto venda populado, inclusive com um produto totalmente preenchido, até aí acho que está certo né?
A dúvida: Dentro do DAO da venda eu teria que buscar o produto da venda por outra consulta SQL, ou poderia utilizar o DAO do produto dentro do DAO da venda para ter reutilização de código? Esse é um exemplo pequeno, agora imagine num sistema onde existe um objeto Empresa que contém Funcionários, Endereços, Bairros, Cidades, Estados, isso traria um ganho realmente muito grande, daí que surgiu a dúvida.

2ª Dúvida:
Meu professor diz que o DAO (camada Model do MVC) não gerencia a conexão (commits e rollbacks), e que quem faria isso seria a camada contendo as regras de negócio.
Ficaria mais ou menos assim:

try {
     vendaDAO.insert(venda);
     produto.setEstoque(produto.getEstoque() - venda.getQuantidade());
     produtoDAO.update(produto);
     conn.commit();
} catch (DAOException e){
     conn.rollback();     
}

Ou seja, é essa camada que se encarrega de inserir uma venda e fazer um update no produto com o novo estoque, e se não der nenhuma exception ele faz um commit, caso aconteça algum problema durante a transação ele faz um rollback.
A maneira correta de fazer é assim mesmo, ou o commit e o rollback ficam dentro dos próprios DAOs?

Agradeço desde já.
Obrigado.

[quote=Cristiano de Barros]Olá amigos do GUJ!
1ª Dúvida:
Quando eu uso o método selectById(int id) do DAO venda, ela já me traz um objeto venda populado, inclusive com um produto totalmente preenchido, até aí acho que está certo né?
A dúvida: Dentro do DAO da venda eu teria que buscar o produto da venda por outra consulta SQL, ou poderia utilizar o DAO do produto dentro do DAO da venda para ter reutilização de código? Esse é um exemplo pequeno, agora imagine num sistema onde existe um objeto Empresa que contém Funcionários, Endereços, Bairros, Cidades, Estados, isso traria um ganho realmente muito grande, daí que surgiu a dúvida.
[/quote]

O mais apropriado seria não ter código duplicado, portanto a reutilização é uma ótima idéia.

  1. DAO não é MVC e MVC e Camadas são coisas diferentes e não relacionadas: http://fragmental.com.br/wiki/index.php?title=MVC_e_Camadas

Controle transacional geralmente é algo feito na Camada de Aplicação (que é mais ou menos onde ficam as regras de negócio). Para entender o porque pense na sua primeira pergunta. Se você reutiliza o primeiro DAO como ficaria se ele controlasse suas próprias transações?

O indicado é você tratar essas buscas e relacionamentos, no caso do uso do DAO comum, através da camada de controle. Deste modo você pode verificar o seguinte: busca uma venda, se acho, busca os produtos, o que melhora o desempenho do seu código evitando consultas desnecessárias. Deve-se evitar estruturas condicionais no DAO, justamente para deixá-lo encarregado de cuidar somente das persistências e consultas.

Quanto ao controle de conexões, eu costumo criar uma classe na camada de persistência para gerenciá-la. Veja abaixo:

public final class ConnectionManager {

private static ConnectionManager instance;

//Cria conexoes para o banco de dados
protected synchronized static ConnectionManager getInstance() {
if( instance == null )
instance = new ConnectionManager();

return instance;

}

//Seta uma conexao livre ou cria uma nova conexao
protected Connection getConnection() {
Connection conn = null;

try {
	Class.forName("com.mysql.jdbc.Driver").newInstance();
	try {
                conn = DriverManager.getConnection("jdbc:mysql://localhost/inet?user=root&password=root");
            }
            catch (SQLException ex) {                    
                System.out.println("SQLException: " + ex.getMessage());
                System.out.println("SQLState: " + ex.getSQLState());
                System.out.println("VendorError: " + ex.getErrorCode());
            }    
    } catch (Exception e) {
	e.printStackTrace();
}		
	
return conn;

}

Você pode criar algum método aqui para cuidar do commit e rollback também.

Espero ter ajudado. Até mais.

Cara esse negócio de camada pensa assim…

Só tem camada se tiver interface…

Se não tem interface não tem camada.

O DAO tem que ser implementado

e fim de papo se não for assim só e algo extruturado e amarrado.

MVC real é vc poder startar os 3 projetos o web, o client e o businnes e eles conversarem entre si por interface.

controle de transação é spring injetando o serviço nunca conn.commit(); Éca…

conexão é JNDI e fim de papo… algo diferente disso é tosco e primata

Pra vislumbrar…

Vc tem um projeto que vai ser feito por 2 fábrica de software.

CADA UMA NA SUA ESPECIALIDADE…

Uma faz a parte View (com telas usando flash, jsf ou struts)

A outra faz a camada de service (client) os serviços que a camada web requer (action) ação = quero listar as vendas , quero gravar o produto…

concorda que vc não precisa ir até o fim pra funcionar a tela ?

os caras nem sabem o que é gravar o produto os caras são designer

A outra são os analistas de negócio que implemantão o DAO os caras que conhecem a regra de negócio.

Agora imagine vc distribuindo essas tarefas…

Vc fala pra fábrica 1…

use o serviço saveSales(SalesDTO) passando um DTO

(entre camadas só pode passar DTO)

Os caras podem testar a tela com dados fake.

Aí vc fala pra fabrica 2

o método saveSales(SalesDTO) tem a seguinte regra…

     salesDTO.insert(venda);   
     produto.setEstoque(produto.getEstoque() - venda.getQuantidade());   
     produtoDAO.update(produto);   

novamente pode ser feito com dados fake pq vão por interface os caras não vão ver o código implmentado.

aki ainda vc manda o cara transformar o seu Bean em um DTO pra devolver pra camada view

E por fim vc com bom analista manda sua equipe implementar o DAO produtoDAO

que vai ter algo do tipo

public void saveOrUpdate(Produto produto) {
 getHibernateTemplate().saveOrUpdate(produto);
}

Aki tem uma parte legal onde vc pode usar DAO dinâmicos mas não tão usuakl prefiro um DAO pra cada coisa.

Espero ter eluciado essa papo de MVC

e só pra se chato hehehe

DAO de insert update tem que ser void sempre otimista

Essa afirmação não tem muito a ver com o padrão definido nem por Fowler nem por Buschmann nem por Evans. Tem alguma referência?

Quanto ao resto do seu post eu não entendi muito bem. MVC também não tem a ver com interface, nem o padrão define “business” ou “client” que você citou. Você afirma que o Spring deve ser utilizado para gerenciar transação, o que é uma boa escolha quando se usa Spring, que não parece ser o caso. Depois fala que “conexão é JNDI”, que além de não estar claro o que significa contradiz a filosofia básica do Spring que você citou anteriormente.

O restante eu realmente não entendi. Fábrica de software? Analista? Onde que isto está relacionado com o problema exposto?

Camarada,

O Cristiano fez uma pergunta simples pra resolver um problema no caso que ele está utilizando. Ele não pediu: “Pessoal, me mandem um monte de coisa falando que o que eu tô fazendo é arcaico!”. Isso só gera mais dúvidas. Você fala de Spring, blá blá blá, mas se esquece de um princípio básico de um bom desenvolvedor: RESOLVER COM SIMPLICIDADE!!!

Pattern é uma padrão certo ? MVC, DAO, DTO e aí vai

usar por usar não tem sentido só pra ficar bonitinho e extruturado ?

Minha indignação é o professores ensinarem que MVC é só isso…

Cara JDNI não tem nada haver com Spring.

blz vou dezenhar…
Seu JNDI ta explicito no nome que é interface…
Java Naming and Directory Interface

<bean id="seuDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
  <property name="jndiName" value="java:comp/env/jdbc/SeuBancoDS" />
</bean>

está mapeado

Agora vamos pro service a camada de serviço on tem os ifs hehe

<bean id="produtoService" class="br.com.ejb.pedido.service.ProdutoServiceImpl">
  <property name="produtoDAO" ref="produtoDAO"/>
</bean>

o controle de transação.

<bean id="seuTxInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
		<property name="transactionManager">
			<bean id="seuTxManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
			    <property name="sessionFactory" ref="seuSessionFactory"/>
			</bean>
		</property>
		<property name="transactionAttributes">
			<props>
				<prop key="save*">PROPAGATION_REQUIRES_NEW</prop>
				<prop key="delete*">PROPAGATION_REQUIRES_NEW</prop>
				<prop key="find*">PROPAGATION_SUPPORTS</prop>
				<prop key="update*">PROPAGATION_REQUIRES_NEW</prop>
			</props>
		</property>
	</bean>

Certo vamos interceptar os métodos que começam com essas palavras e pra cada tipo um tipo de transação.

Agora vamos aos hbms…

<bean id="seuSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource" ref="seuDataSource" />
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
				<prop key="hibernate.show_sql">false</prop>
				<prop key="hibernate.jdbc.use_streams_for_binary">false</prop>
				<prop key="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</prop>
			</props>
		</property>
		<property name="mappingResources">
			<list>
				<value>br/com/ejb/model/hbm/Produto.hbm.xml</value>
			</list>
		</property>
	</bean>		

Blz ?

na camada Web numa action…

 service.saveProduto(produtoDTO);

na client (camada burra só tem DTO e os services a serem implementados)
lembra que setamos o seuService

public interface ProdutoService {
public void saveProduto(Produto protudoDTO) throws SuaException;

agora vamos pra camada businnes

/** DAO para gravar o produto. */
private ProdutoDAO produtoDAO;

// injetando o dao que vc definiu no spring 

public void setProdutoDAO(ProdutoDAO produtoDAO) {
 this.produtoDAO = produtoDAO;
}

ainda na camada de negócio (nosso service)

private saveProduto(ProdutoDTO dto) {
// vamos transformar o DTO em Bean (model) num método é claro
Produto bean = new Produto();
bean.setId(dto.getId());
bean.setDesc(dto.getDesc());

saveProduto(bean);
// agora vai ser interceptado a transação do tipo de vc setou... lembra ? PROPAGATION_REQUIRES_NEW
}

o DAO interface

public interface ProdutoDAO {
public void saveProduto(Produto produto);
}

Agora a implementação do seu DAO

public void saveProduto(Produto produto) {
 getHibernateTemplate().save(produto);
}

demorado mais elegante…

como seu o seu própio link disse…

Utilizando Camadas o projetista tem um critério a utilizar quando decide agrupar duas ou mais classes, mas o uso de Camadas não diz nada sobre como estes grupos se comunicam. O máximo que o uso de Camadas diz é sobre se estas são transparentes (ou abertas) ou opacas (fechadas). Camadas transparentes não evitam que uma superior enxergue a inferior, as opacas sim.

As Camadas promovem o encapsulamento (uma Camada não vai saber o que tem dentro da outra) e a coesão (componentes parecidos ficam no mesmo grupo).

se não usar interface vai ser Camadas transparentes não evitam que uma superior enxergue a inferior

tosco pra quem vai distribuir um trabalho entre diferentes fornecedore.

VC DISSE Fábrica de software? Analista? Onde que isto está relacionado com o problema exposto?

Talves me não devia ter usado Analista e sim projetista e não usar Fábrica de software e sim seu amigo de baia

Aí que tá o problema pcalcado esses caras aprendem desse jeito e na hora de trabalhar não sabem o que estão fazendo e pipoca

o código de try catch e outra pérolas…

mas agoar vc me falar que … conexão é JNDI", não estar claro o que significa contradiz a filosofia básica do Spring tsc tsc tsc tsc…

tem que usar isso mesmo

conn = DriverManager.getConnection("jdbc:mysql://localhost/inet?user=root&password=root"); 

heheh é a password é root

[quote=geidivan]Camarada,

O Cristiano fez uma pergunta simples pra resolver um problema no caso que ele está utilizando. Ele não pediu: “Pessoal, me mandem um monte de coisa falando que o que eu tô fazendo é arcaico!”. Isso só gera mais dúvidas. Você fala de Spring, blá blá blá, mas se esquece de um princípio básico de um bom desenvolvedor: RESOLVER COM SIMPLICIDADE!!![/quote]

Não concordo.
Olha o nome do tópico
Dúvida sobre DAO
o cara tá aprendendo tem que evoluir… quer aprender… tem que ensinar o mais atual…

vc tem um carro a carburador eu falao de trocar por injeção e vc reclama ?
Arruma o carburador em um desmanche então e nunca mais volta na mnha oficina de tunning

O bom desenvolvedor RESOLVE COM COMPLEXIDADE EM ALTO NÍVEL, no mesmo tempo que um novato RESOLVE COM SIMPLICIDADE.

E depois no primeiro realese de código ou mudança na regra de negócio babau… vai demorar muito

ou a clássica resposta melhor fazer de novo…

MAS BLZ…

quem quer ganhar só 30 conto a hora tem que fazer asim mesmo displicentemente. só que eu não contrataria um cara desses

Pessoal, agradeço pelas respostas, o link do Shoes clareou bastante o conceito de MVC, e suas diferenças em relação a Camadas, mas ainda estou com algumas dúvidas…

A parte do gerenciamento da conexão eu entendi bem, acho que o correto seria gerenciar isso fora dos DAOs mesmo.

Agora voltando para a reutilização do DAO, traduzindo o raciocínio do geidivan para um exemplo, eu poderia fazer o VendaDAO retornar um objeto Venda, onde seu produto teria somente o id (os atributos da venda estariam preenchidos normalmente), e na camada de controle eu consultaria o produto pelo id utilizando o ProdutoDAO, a camada de controle se encarregaria de “montar” o objeto venda devidamente?
Parece que assim fica mais dividido, e não utilizaria o ProdutoDAO dentro do VendaDAO diretamente… Está correto assim? Opiniôes? :smiley:

[Edit]:
Eu sei que hoje em dia grandes empresas utilizam frameworks para ter maior agilidade (como Hibernate), mas eu considero fundamental pra mim aprender esse tipo de coisa. É lógico que se na empresa onde eu for trabalhar utilizarem Hibernate por exemplo, vou trabalhar com ele, mas eu considero fundamental sabe trabalhar com e sem esses frameworks. :smiley:

[quote=focao][/quote]

Acho que você pode estar confundindo alguns conceitos, o que não é muito difícil dado que a mensagem original já os confundia.

Antes de mais nada, DAO e MVC não têm relação alguma um com o outro. MVC fica na Camada de Apresentação, DAO na Camada de Persistência. Você ode ter os dois no mesmo sistema ou não. Sobre DTO, eu gostaria de falar mais sobre este tema mas vai desvirtuar o tópico então (enquanto o jforum não possui fork/join de threads) eu sugiro que você leia alguns destes tópicos antigos: http://www.google.com.au/search?q=site%3Aguj.com.br+DTO

Sobre JNDI, a tecnologia não tem a ver com Spring (na verdade tem, já que Spring pode abstrair JNDI, mas no contexto deste post não tem) mas eles se baseiam em filosofias diferentes. JNDI é uma implementação do padrão Registry, Spring é uma implementação de Dependency Injection. Você ode ter os dois no sistema mas não é lá muito sadio, já que você citou Spring seria bom manter tudo em DI. Dizer que “conexão é JNDI” não faz sentido já que o próprio Spring que você citou pode fazer isso sem JNDI.

Eu não entendi onde o seu “desenho” entra em qualquer dos pontos que citei na mensagem anterior.

Você bateu exatamente na barreira que torna usar JDBC diretamente extremamente trabalhoso e que faz com que Hibernates e JPAs brilhem.

Eu já implementei sistemas razoavelmente grandes utilizando DAOs com JDBC e até hoje não vi uma resposta decente para sua pergunta. Normalmente os DAOs acabam com diversos métodos do tipo: retornaUsuario(), retornaUsuarioComGrupo(), retornaGrupo(), retornaGrupoComUsuarios()…

Não existe, AFAIK, uma solução que não envolva algo tão complexo que se torne seu próprio framework ORM. Se você continuar utilizando JDBC puro tente minimizar o que a Camada de Aplicação/Negócios precisa saber sobre DAOs (do tipo saber que o método X retorna Usuario sem o grupo e por isso você precisa buscar o grupo).

Indo um pouco mais além, você ode fazer seu DAO retornar objetos decorados (design pattern Decorator) onde os decoradores fazem um lazy-loading simples. Pode ser eficiente, pode não ser.

Acho que isso torna um pouco confuso para um iniciante. No inglês, Model-View-Controller são tidos como Layers (Camadas). Acontece que, camadas físicas, (tiers), são outras coisas.
Afirmar que MVC e Camadas são diferentes, seria obviamente confuso, pois estamos dando outra norma para a tradução, o que não é correto. Layer não deixou de ser camada.
Agora, tier não, possui várias formas de traduzir (Camada, Nível, Fila).
Além do mais, creio que o colega ai está confundindo o que o professor diz. Não acredito que alguém diria tamanha besteira misturando DAO e MVC.

[quote=djemacao]
Acho que isso torna um pouco confuso para um iniciante. No inglês, Model-View-Controller são tidos como Layers (Camadas). Acontece que, camadas físicas, (tiers), são outras coisas.
Afirmar que MVC e Camadas são diferentes, seria obviamente confuso, pois estamos dando outra norma para a tradução, o que não é correto. Layer não deixou de ser camada.
Agora, tier não, possui várias formas de traduzir (Camada, Nível, Fila).
Além do mais, creio que o colega ai está confundindo o que o professor diz. Não acredito que alguém diria tamanha besteira misturando DAO e MVC.[/quote]

Interessante… em qual bibliografia? Em nenhum dos paper originais (http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html) existe a palavra layer como componente do MVC. Bibliorafias de respeito (POEAA por exemplo) também não o fazem. Será que você não está se baseando em uma bibliografia questionável para a conclusão acima?

Quando eu disse isso, eu estava querendo dizer que o DAO fazia parte da camada Model do MVC, não que o DAO era o Model. Confesso que até eu lendo agora não parece que estava querendo dizer isso, mas acredite, eu estava. :slight_smile:
Mesmo assim com suas respostas me ajudaram a entender (e diferenciar) melhor MVC, DAO e Camadas.

Quanto a conclusão que eu cheguei, é que não existe uma maneira que vai resolver o problema de todo mundo.
Pesquisando sobre as técnicas que o Shoes comentou, achei uma alternativa interessante (e que faz o lazy-loading como ele comentou), o uso de objetos Proxy para encapsular o objeto real dentro de um outro objeto que utiliza a mesma interface, e assim carregar os objetos somente quando você realmente precisar (inclusive o Hibernate funciona assim).
http://www.devmedia.com.br/articles/viewcomp.asp?comp=4066

Agradeço pelas respostas de todos!
Um abraço.

[quote=pcalcado][quote=djemacao]
Acho que isso torna um pouco confuso para um iniciante. No inglês, Model-View-Controller são tidos como Layers (Camadas). Acontece que, camadas físicas, (tiers), são outras coisas.
Afirmar que MVC e Camadas são diferentes, seria obviamente confuso, pois estamos dando outra norma para a tradução, o que não é correto. Layer não deixou de ser camada.
Agora, tier não, possui várias formas de traduzir (Camada, Nível, Fila).
Além do mais, creio que o colega ai está confundindo o que o professor diz. Não acredito que alguém diria tamanha besteira misturando DAO e MVC.[/quote]

Interessante… em qual bibliografia? Em nenhum dos paper originais (http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html) existe a palavra layer como componente do MVC. Bibliorafias de respeito (POEAA por exemplo) também não o fazem. Será que você não está se baseando em uma bibliografia questionável para a conclusão acima?[/quote]
Então, me ajude a interpretar isso:
http://java.sun.com/blueprints/guidelines/designing_enterprise_applications_2e/app-arch/app-arch2.html#1105855

Está escrito LAYERS, correto?

[EDITADO]
Bacana o paper original pcalcado, porém, nem o Java e acho que quase nenhuma linguagem utiliza o MVC original. Vejo o Django interpretando o MVC de sua forma, o Rails de sua forma. São baseados e não exatamente eles em si.
[/EDITADO]

Desculpe se estou questionando você, pcalcado , é que, como disse em seu próprio artigo, não existem muitas literaturas a respeito, mas vários livros tratam dessa forma descrita.

Acho que você pode estar confundindo alguns conceitos, … MVC fica na Camada de Apresentação, …
[/quote]

aiaiaia… fica onde ? my Gd

Equece é um o padrão se é um padrão não pode tá em nenhuma camada.

Define o padrão de divisão de camadas Layer o que vcs quiserem

E continuo com minha afirmação MVC sem interface não é MVC

Até as referência que vc cita diz isso.

Este modelo foi criado em Smalltalk e traz simplicidade e coerência( à interfaces).

Mas blz bom pro forum essas disconrdâncias…

abçs…