wiki:WF/RecomendacoesdeusodeBancodeDados

Version 12 (modified by viani, 12 years ago) (diff)

--

Conexão com Banco de Dados

Classe: wf_db

A classe que é utilizada nos processos de Workflow para fazer conexão com o banco de dados é a wf_db. Esta classe faz uso do  ADOdb como camada de abstração de banco de dados.

A documentação da classe pode ser vista na documentação do código fonte do Workflow

Os métodos básicos da classe são:

  • connect - conecta-se ao banco de dados (por padrão, conecta-se ao banco de dados onde da base de dados do processo de Workflow);
  • disconnect - desconecta-se do banco de dados;
  • query - executa um comando SQL no banco de dados.

Objeto

O objeto da classe wf_db já vem criado por padrão no desenvolvimento utilizando o MVC proposto - Arquitetura de Desenvolvimento.

Ele pode ser acessado em qualquer classe model através do atributo $this->DAO

Bind

A versão atual do ADOdb utilizada permite a utilização de bind para a execução de queries. A idéia do bind é aproveitar o mesmo plano de execução para as mesmas ações. Na utilização do bind os valores (inseridos, atualizados ou de consulta) são separados da query. Exemplo de utilização de bind:

/* SEM BIND */

$this->DAO->query("INSERT INTO usuario(usuario_id, nome) VALUES(1, 'João')"); //plano de execução 1

$this->DAO->query("INSERT INTO usuario(usuario_id, nome) VALUES(2, 'Maria')"); //plano de execução 2

/* COM BIND */

$this->DAO->query('INSERT INTO usuario(usuario_id, nome) VALUES(?, ?)', array(1, 'João')); //plano de execução 3

$this->DAO->query('INSERT INTO usuario(usuario_id, nome) VALUES(?, ?)', array(2, 'Maria')); //plano de execução 3

Repare que utilizando o bind, o plano de execução para as queries é o mesmo pois, a única coisa que muda são dos dados, a query é a mesma. Já sem a utilização de bind, as queries são diferentes, uma vez que os dados fazem parte da query, gerando diferentes queries para diferentes dados. Outras vantagens de se utilizar o bind sobre o método "tradicional" são:

  • O parser do banco de dados não precisa analisar queries que podem ser de grande tamanho devido aos dados que estão sendo inseridos (e.g. inserção de arquivos em banco, neste caso a query terá praticamente o tamanho do arquivo inserido);

Como pode ser visto no exemplo, ao invés de se inserir os valores na query, utiliza-se {{?}} para cada valor e, depois os valores são passados em uma {{array}} como segundo parâmetro do método query. Os itens da array seguem a ordem das {{?}} utilizadas.

Utilização

Antes de utilizar o objeto para acesso ao Banco de Dados, é necessário conectá-lo ao banco. Para isto, basta chamar o método {{connect}}. Caso o banco que se quer conectar é o banco do próprio processo, não é necessário passar parâmetros, sendo a chamada realizada da seguinte maneira:

$this->DAO->connect();

Em todos os exemplos vamos considerar que a conexão com o Banco de Dados já foi feita.

SELECT

/* Exemplo 01 */

$resultSet = $this->DAO->query('SELECT usuario_id, nome FROM usuario');

$data = array();

while ($row = $resultSet->fetchRow())

	$data[] = $row;

/* a variável $data será uma array com os valores selecionados */

echo $data[0]['nome']; //exemplo de acesso aos dados (nome do primeiro registro retornado)


/* Exemplo 02 */

$resultSet = $this->DAO->query('SELECT usuario_id, nome FROM usuario WHERE (nome = ?)', array('José'));

$data = array();

while ($row = $resultSet->fetchRow())

	$data[] = $row;

INSERT

$result = $this->DAO->query("INSERT INTO area(area_id, nome) VALUES(?, ?)", array(1, 'DISER'));

if ($result)

	echo "OK";

else

	echo "Erro na execução da query";

UPDATE

/* troca o nome do usuário José para Joselito

$result = $this->DAO->query("UPDATE usuario SET nome = ? WHERE (nome = ?)", array('Joselito', 'José'));

DELETE

/* apaga o usuário cujo ID é 3 */

$result = $this->DAO->query("DELETE FROM usuario WHERE (usuario_id = ?)", array(3));

Tratamento de Erros

TODO: <<explicar como obter o código de erro>>

Casos Especiais

Inserção de Arquivos no Banco de Dados

O procedimento para inserir o conteúdo de um arquivo no Banco de Dados, requer uma pequena modificação que faz o tratamento do conteúdo antes de inseri-lo. Este tratamento é feito através da chamada ao método {{escapeBytea}}:

/* supondo que $bin possua o conteúdo do arquivo */

$bin = $this->DAO->escapeBytea($bin);

$result = $this->DAO->query("INSERT INTO tabela_arquivo(nome, conteudo) VALUES(?, ?)", 
      array('arquivo.dat', $bin));

Transações

Em alguns casos, é vital a utilização de transações. Sua utilização é muito simples, como pode ser visto abaixo:

/* neste exemplo criamos uma área e tentamos colocar o funcionário José nesta nova área.

 * Em caso de erro, esta área não deverá ser criada.

 */

$result = true;

$this->DAO->startTrans();

$result = $result && $this->DAO->query("INSERT INTO area(area_id, nome) VALUES(?, ?)", array(10, 'NOVA ÁREA'));

$result = $result && $this->DAO->query("UPDATE funcionario SET area_id = ? WHERE (nome = ?)", array(10, 'José'));

if ($result)

	$this->DAO->completeTrans(); // faz o commit das alterações

else

	$this->DAO->failTrans(); // faz o rollback das alterações

Conectar a Outro Banco de Dados

Além do banco workflow, que está acessível pelo objeto $this->DAO, previamente fornecido pelo ambiente de execução de uma atividade, existe a possibilidade de criar novos objetos DAO, e conectá-los a outros bancos de dados. O procedimento é sempre o mesmo, variando os parâmetros passados para o método connect da classe wf_db.

Exemplo:

// cria uma nova instância da classe wf_db
$conn = Factory::newInstance('wf_db');


// conecta-se ao banco de dados
$conn->connect('nome_database', 'host', porta, 'usuario', 'senha');

// Verifica se a conexão foi bem sucedida
if ($conn)
{
	// executa uma query
	$recordSet = $conn->query('SELECT campo1, campo2 FROM esquema.tabela');

	// verifica se a query foi executada com sucesso */
	if ($recordSet)
	{
		// percorre os dados da consulta
		while (!$recordSet->EOF)
		{
			print_r($recordSet->fields);
			$recordSet->MoveNext();
		}
	}
}

// desconecta-se do banco
$conn->disconnect();