Arquivo da categoria ‘C/C++’

No ciência da computação, Data Access Object é um padrão para um objeto que fornece uma interface abstrata para algum tipo de banco de dados ou outro mecanismo de persistência e que permite separar regras de negócio das regras de acesso a banco de dados. A vantagem de usar objetos de acesso a dados é a separação simples e rigorosa entre duas partes importantes de uma aplicação que não devem e não podem conhecer quase que nada uma da outra, e que podem evoluir frequentemente e independentemente.

O DAO implementa o mecanismo de acesso necessário para trabalhar com a fonte de dados. A fonte de dados pode ser um armazenamento persistente como um RDBMS, um serviço externo, como uma troca de B2B, um repositório como um banco de dados LDAP, um serviço de negócios acessado via CORBA, Internet Inter-ORB Protocol (IIOP) ou soquetes de baixo nível. O componente de negócio que se baseia no DAO usa a interface mais simples exposta pelo DAO para seus clientes.

Microsoft, C++ e DAO

O DAO Pattern J2EE não deve ser confundido com o DAO método de acesso a dados da Microsoft . O DAO (Microsoftfornece um quadro para a utilização de código para criar e manipular bancos de dados através de um conjunto hierárquico de objetos que usam o mecanismo de banco de dados Microsoft Jet para arquivos MDB, ou através de ODBC ou também banco de dados IASM como o antigo DBase, Paradox entre outros. O DAO Microsoft também é suportado em C++ através das classes de fundação da Microsoft (MFC).

Devido algumas similaridades do C++ com o Java é possível utilizar integralmente o DAO Pattern que é um padrão já consagrado por desenvolvedores Java para separar a camada de negocio da camada do banco de dados. O DAO é um célebre Pattern utilizado sozinho ou também em conjunto com outros frameworks, provavelmente alguns desenvolvedores C++ já o utilizaram de algum modo, implicitamente ou explicitamente, mesmo sem o conhecer em detalhes.

C++ - MFC - DAO

C++ – MFC – DAO

DAO Pattern

O DAO é um padrão flexível e não uma regra ele é utilizado em conjunto com Factory Pattern e Broker Pattern (veja Patterns relacionados no link abaixo) por isto é comum você encontrar algumas variações de sua implementação, o padrão possui quatro especificações para que possa ser utilizado corretamente elas são: DataAccessObject, DataSourceObject, BussinesObject e TransferObject.

  1. DataAccessObjecté o objeto principal desse padrão. O Data Access Object abstrai a implementação fundamental de acesso a dados para o Business Objects para permitir acesso transparente à fonte de dados.
  2. DataSourceObjectrepresenta uma implementação da fonte de dados. Uma fonte de dados pode ser uma base de dados tal como um RDBMS, repositório XML, e assim por diante.
  3. BussinesObject – o objeto de negócios representa o dados do cliente. É o objeto que requer acesso à fonte de dados para obter e armazenar dados.
  4. TransferObjectrepresenta um objeto de transferência usado como um suporte de dados. O Data Access Object pode usar um objeto de transferência para retornar dados para o cliente. O Data Access Object também pode receber os dados do cliente em um objeto de transferência para atualizar os dados na fonte de dados.

DAO Pattern: http://www.oracle.com/technetwork/java/dataaccessobject-138824.html

CRUD – DAO

CRUD acrónimo de Create, Read, Update e Delete, utiliza as quatro operações básicas  para criação, consulta, atualização e exclusão de dados.

Através do padrão DAO vamos utilizar as operações CRUD para manipular dados no banco de dados. O DAO é um Pattern J2EE, mas como ele separa as regras de negocio do acesso a dados também podemos utiliza-lo com qualquer tipo de interface, seja pela linha de comando, uma GUI desktop ou aplicações web.

Para usar o DAO você utiliza o Factory Pattern para criar uma abstração para o acesso a dados e uma classe concreta para seu tipo de acesso como por exemplo OracleDAOFactory, DB2DAOFactory e assim por diante. Então você pode criar a interface para seu objeto DAO chamada DAOFuncionario e a partir da interface você pode criar as classes DAO como, DAOFuncionarioOracle, DAOFuncionarioDB2 e utiliza o objeto de transferência para manipular dados.

Neste exemplo não criamos uma classe abstrata utilizando o Pattern Factory Method, cortamos caminho pois utilizamos apenas um objeto DAO para todos os bancos de dados, mas caso deseje criar uma abstração para classes concretas para cada banco de dados siga a especificação oficial do DAO Pattern no link logo acima.

Visual Studio - Design

Visual Studio – Design

Utilize a imagem acima para criar um design parecido.

Exemplo:

Neste exemplo usamos o Pattern DAO para criar operações CRUD utilizando uma interface gráfica, como este exemplo não possuí uma tela de login mude o acesso ao banco e usuário e senha diretamente na classe FuncionarioDAO.

O DAO  pode ser utilizado para varias soluções como no exemplo abaixo para enfatizar sua eficiência utilizamos o DAO em uma interface gráfica escrita com MFC justamente para mostrar a independência do negocio e acesso a dados.

Este é o terceiro método que disponibilizamos para manipular dados através de um banco de dados, para ver este mesmo programa utilizando SQL direto da aplicação clique aqui.

Pare ver este programa usando objetos no banco de dados como Views e Triggers clique aqui ou procure na busca também por Stored Procedures e cursores.

Ainda veremos outros métodos para manipular dados através de frameworks específicos.

SQL

Oracle

-- Cria tabela de funcionarios
create table Funcionarios(
  ID_Funcionario  NUMBER(5),
  Nome            VARCHAR2(30),
  Sobrenome       VARCHAR2(70),
  Cargo           VARCHAR2(30),
  Salario         NUMBER(9,2));

DB2

-- Cria tabela de funcionarios
create table Funcionarios (
    ID_Funcionario  INTEGER,
    Nome            VARCHAR(30),
    Sobrenome       VARCHAR(70),
    Cargo           VARCHAR(30),
    Salario         NUMERIC(9,2));

MSSQL

-- Cria tabela de funcionarios
create table Funcionarios (
   ID_Funcionario  Int,
   Nome            VARCHAR(30),
   Sobrenome       VARCHAR(70),
   Cargo           VARCHAR(30),
   Salario         Decimal(9,2));

C++

Objeto – Negócio

Header

#pragma once

class Funcionario
{

private:
	// Atributos
	long id;
	CString nome;
	CString sobrenome;
	CString cargo;
	double  salario;

public:

	// Construtor
	Funcionario();
	~Funcionario();

	// Construtor Overload
	Funcionario(long id, CString nome, CString sobrenome, CString cargo, double salario);

	// Metodos Getter e Setter
	void setId(long id);
	long getId();

	void setNome(CString nome);
	CString getNome();

	void setSobrenome(CString sobrenome);
	CString getSobrenome();

	void setCargo(CString cargo);
	CString getCargo();

	void setSalario(double salario);
	double getSalario();

};

Cpp

#include "stdafx.h"
#include "Funcionario.h"

// Implementação da classe Funcionarios

Funcionario::Funcionario()
{
}

Funcionario::~Funcionario()
{
}

// Construtor Overload
Funcionario::Funcionario(long id, CString nome, CString sobrenome, CString cargo, double salario)
{
	this->id = id;
	this->nome = nome;
	this->sobrenome = sobrenome;
	this->cargo = cargo;
	this->salario = salario;
}

// Getters e Setters
void Funcionario::setId(long id)
{
	this->id = id;
}

long Funcionario::getId()
{
	return this->id;
}

void Funcionario::setNome(CString nome)
{
	this->nome = nome;
}

CString Funcionario::getNome()
{
	return this->nome;
}

void Funcionario::setSobrenome(CString sobrenome)
{
	this->sobrenome = sobrenome;
}

CString Funcionario::getSobrenome()
{
	return this->sobrenome;
}

void Funcionario::setCargo(CString cargo)
{
	this->cargo = cargo;
}

CString Funcionario::getCargo()
{
	return this->cargo;
}

void Funcionario::setSalario(double salario)
{
	this->salario = salario;
}

double Funcionario::getSalario()
{
	return this->salario;
}

Factory Pattern – DAConexaoFactory

Header

#pragma once

// Inclui classe de banco de dados MFC
#include "afxdb.h"

class DAConexaoFactory
{
private:

	// Define constantes para fonte de dados
	const int ORACLE = 1;
	const int DB2 = 2;
	const int MSSQL = 3;

	// Define dados do usuario
	CString dns, usuario, senha;

	// Define banco de dados

public:

	DAConexaoFactory();
	~DAConexaoFactory();

	CString getConexao(int banco);
};

Cpp

#include "stdafx.h"
#include "DAConexaoFactory.h"

DAConexaoFactory::DAConexaoFactory()
{
}

DAConexaoFactory::~DAConexaoFactory()
{
}

CString DAConexaoFactory::getConexao(int banco)
{

	// Define banco de dados
	if (banco == ORACLE)
	{
		dns = L"OracleXE";
		usuario = L"user";
		senha = L"pass";
	}

	if (banco == DB2)
	{
		dns = L"IBMDB2";
		usuario = L"user";
		senha = L"pass";
	}

	if (banco == MSSQL)
	{
		dns = L"MSSQLSERVER";
		usuario = L"user";
		senha = L"pass";
	}

	// Cria string de conexão ODBC
	CString conexao;

	// Cria string de conexão
	conexao = L"DSN=" + dns + L";UID=" + usuario + L";PWD=" + senha;

	// Abre conexão

	return  conexao;
}

Objeto DAO – FuncionarioDAO

Header

#pragma once

#include "afxdb.h"
#include "IDaoFuncionario.h"

class FuncionarioDAO
{

private:
	// Define objetos
	CDatabase conn;
	CString erro;
	TCHAR menssagem[255];

public:	

	FuncionarioDAO();
	~FuncionarioDAO();

	// Metodos DAO

	Funcionario buscaFuncionario(CString id);

	bool insereFuncionario(Funcionario& funcionario);

	bool alterarFuncionario(Funcionario& funcionario);

	bool deletarFuncionario(Funcionario& funcionario);

	CString getErro();

};

Cpp

#include "stdafx.h"
#include "FuncionarioDAO.h"
#include "DAConexaoFactory.h"

FuncionarioDAO::FuncionarioDAO()
{
	DAConexaoFactory conexao = DAConexaoFactory();
	conn.OpenEx(conexao.getConexao(1), 0);

}

FuncionarioDAO::~FuncionarioDAO()
{
}

Funcionario FuncionarioDAO::buscaFuncionario(CString id)
{
	// Cria objeto de negocio
	Funcionario funcionario = Funcionario();
	CString m_conteudo;

	try
	{
		// Define Set de dados
		CRecordset dados(&conn);

		// Executa SQL
		dados.Open(CRecordset::forwardOnly,
			L"Select * From Funcionarios Where  ID_FUNCIONARIO = " + id);

		// carrega dados no objeto
		dados.GetFieldValue(L"ID_FUNCIONARIO", m_conteudo);
		funcionario.setId(_wtoi(m_conteudo));
		dados.GetFieldValue(L"NOME", m_conteudo);
		funcionario.setNome(m_conteudo);
		dados.GetFieldValue(L"SOBRENOME", m_conteudo);
		funcionario.setSobrenome(m_conteudo);
		dados.GetFieldValue(L"CARGO", m_conteudo);
		funcionario.setCargo(m_conteudo);
		dados.GetFieldValue(L"SALARIO", m_conteudo);
		m_conteudo.Replace(_T(","), _T("."));
		funcionario.setSalario(_wtof(m_conteudo));

		dados.Close();
	}
	catch (CDBException* ex )
	{
		// Define erro
		ex->GetErrorMessage(menssagem, 255);
	    erro += menssagem ;
	}

	// Retorna objeto
	return funcionario;
}

bool FuncionarioDAO::insereFuncionario(Funcionario& funcionario)
{
	// Define variaveis
	CString m_id;
	CString m_salario;

	// Formata valores
	long id = funcionario.getId();
	m_id.Format(_T("%ld"), id);

	double salario = funcionario.getSalario();
    m_salario.Format(_T("%g"), salario);

	// Cria instrução SQL
	CString sql = L"Insert into  Funcionarios  values ( " + m_id + ", " +
		"'" + funcionario.getNome() + "', " +
		"'" + funcionario.getSobrenome() + "', " +
		"'" + funcionario.getCargo() + "', " +
		m_salario + ")";

	try
	{
		// Executa SQL
		conn.ExecuteSQL(sql);
		return true;
	}
	catch (CDBException* ex)
	{
		// Define erro
		ex->GetErrorMessage(menssagem, 255);
		erro += menssagem;
		return false;
	}

}

bool FuncionarioDAO::alterarFuncionario(Funcionario& funcionario)
{
	// Define variaveis
	CString m_id;
	CString m_salario;

	// Define valores
	long id = funcionario.getId();
	m_id.Format(_T("%ld"), id);

	double salario = funcionario.getSalario();
	m_salario.Format(_T("%g"), salario);

	// Cria instrução SQL
	CString sql = L"Update  Funcionarios  set ID_FUNCIONARIO = " + m_id + ", " +
		" NOME= '" + funcionario.getNome() + "', " +
		" SOBRENOME= '" + funcionario.getSobrenome() + "', " +
		" CARGO = '" + funcionario.getCargo() +
		" ', SALARIO = " + 	m_salario +
		" WHERE ID_FUNCIONARIO = " + m_id ;

	try
	{
		// Executa SQL
		conn.ExecuteSQL(sql);
		return true;
	}
	catch (CDBException* ex)
	{
		// Define erro
		ex->GetErrorMessage(menssagem, 255);
		erro += menssagem;
		return false;
	}

}

bool FuncionarioDAO::deletarFuncionario(Funcionario& funcionario)
{
	// Define variaveis
	CString m_id;

	// Define valores
	long id = funcionario.getId();
	m_id.Format(_T("%ld"), id);

	// Cria instrução SQL
	CString sql = L"Delete from  Funcionarios WHERE ID_FUNCIONARIO = " + m_id;

	try
	{
		// Executa SQL
		conn.ExecuteSQL(sql);
		return true;
	}
	catch (CDBException* ex)
	{
		// Define Erro
		ex->GetErrorMessage(menssagem, 255);
		erro += menssagem;
		return false;
	}
}

CString FuncionarioDAO::getErro()
{
	// Retorna Erro
	return erro;
}

GUI – DADaoApp

Header


// CamposcppDlg.h : header file
//

#pragma once

#include "afxwin.h"

// CCamposcppDlg dialog
class CCamposcppDlg : public CDialogEx
{

public:
	CCamposcppDlg(CWnd* pParent = NULL);	// standard constructor

// Dialog Data
	enum { IDD = IDD_CAMPOSCPP_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support

// Implementation
protected:
	HICON m_hIcon;

	// Generated message map functions
	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()

public:

	// Variaveis Edits
	CEdit m_pesquisa;
	CEdit m_codigo;
	CEdit m_pnome;
	CEdit m_snome;
	CEdit m_cargo;
	CEdit m_salario;

	// Variaveis Botões
	CButton m_apagar;
	CButton m_novo;

	// Eventos
	afx_msg void OnShowWindow(BOOL bShow, UINT nStatus);
	afx_msg void OnBnClickedButton1();
	afx_msg void OnBnClickedButton2();
	afx_msg void OnBnClickedButton3();
	afx_msg void OnBnClickedButton4();
	afx_msg void OnBnClickedButton5();

private:

	// Campos
	CString codigo;
	CString pnome;
	CString snome;
	CString cargo;
	CString salario;

};

Cpp


// CamposcppDlg.cpp : implementation file
//

#include "stdafx.h"
#include "afxwin.h"
#include "Camposcpp.h"
#include "CamposcppDlg.h"
#include "afxdialogex.h"
#include "Funcionario.h"
#include "FuncionarioDAO.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

CCamposcppDlg::CCamposcppDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CCamposcppDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CCamposcppDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_EDIT6, m_pesquisa);
	DDX_Control(pDX, IDC_EDIT1, m_codigo);
	DDX_Control(pDX, IDC_EDIT2, m_pnome);
	DDX_Control(pDX, IDC_EDIT3, m_snome);
	DDX_Control(pDX, IDC_EDIT4, m_cargo);
	DDX_Control(pDX, IDC_EDIT5, m_salario);
	DDX_Control(pDX, IDC_BUTTON5, m_apagar);
	DDX_Control(pDX, IDC_BUTTON2, m_novo);

}

BEGIN_MESSAGE_MAP(CCamposcppDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, &CCamposcppDlg::OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON2, &CCamposcppDlg::OnBnClickedButton2)

ON_WM_SHOWWINDOW()
ON_BN_CLICKED(IDC_BUTTON3, &CCamposcppDlg::OnBnClickedButton3)
ON_BN_CLICKED(IDC_BUTTON4, &CCamposcppDlg::OnBnClickedButton4)
ON_BN_CLICKED(IDC_BUTTON5, &CCamposcppDlg::OnBnClickedButton5)
ON_WM_CTLCOLOR()
END_MESSAGE_MAP()

BOOL CCamposcppDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	SetIcon(m_hIcon, TRUE);
	SetIcon(m_hIcon, FALSE);
	return TRUE;
}

void CCamposcppDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); 

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

HCURSOR CCamposcppDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

// ************************         Desenvolvimento Aberto
// Nosso código começa aqui

void CCamposcppDlg::OnBnClickedButton1()
{
	// Referincia objeto statico
	CWnd * p_rotulo;

	// Associa objeto statico
	p_rotulo = GetDlgItem(IDC_Rotulo);
	p_rotulo->SetWindowTextW(L"DAO - Pattern");

	// Define variaveis
	CString codigo;

	// Cria objetos DAO
	Funcionario funcionario = Funcionario();
	FuncionarioDAO pesquisar = FuncionarioDAO();

	// Cria pesquisa
	m_pesquisa.GetWindowTextW(codigo);

	// Busca objeto
	funcionario = pesquisar.buscaFuncionario(codigo);

	// recupera dados do objeto e transfere para a GUI
	CString m_conteudo;
	long m_id = funcionario.getId();
	m_conteudo.Format(_T("%ld"), m_id);

	m_codigo.SetWindowTextW(m_conteudo);
	m_pnome.SetWindowTextW(funcionario.getNome());
	m_snome.SetWindowTextW(funcionario.getSobrenome());
	m_cargo.SetWindowTextW(funcionario.getCargo());

	double m_sal = funcionario.getSalario();
	m_conteudo.Format(_T("%g"), m_sal);
	m_salario.SetWindowTextW(m_conteudo);
}

void CCamposcppDlg::OnBnClickedButton2()
{
	// Limpa componentes
	m_codigo.SetWindowTextW(NULL);
	m_pnome.SetWindowTextW(NULL);
	m_snome.SetWindowTextW(NULL);
	m_cargo.SetWindowTextW(NULL);
	m_salario.SetWindowTextW(NULL);

	// Define foco
	CEdit* pesquisa;
	pesquisa = (CEdit*)GetDlgItem(IDC_EDIT1);
	GotoDlgCtrl(pesquisa);
}

void CCamposcppDlg::OnShowWindow(BOOL bShow, UINT nStatus)
{
	CDialogEx::OnShowWindow(bShow, nStatus);

	// Define foco inicial
	CEdit* pesquisa;
	pesquisa = (CEdit*)GetDlgItem(IDC_EDIT6);
	GotoDlgCtrl(pesquisa);
}

// Clique do botão inserir
void CCamposcppDlg::OnBnClickedButton3()
{
	// Recupara texto dos componentes
	m_codigo.GetWindowTextW(codigo);
	m_pnome.GetWindowTextW(pnome);
	m_snome.GetWindowTextW(snome);
	m_cargo.GetWindowTextW(cargo);
	m_salario.GetWindowTextW(salario);

	// Troca ponto decimal para o banco de dados
	int i = salario.Replace(L",", L".");

	// Cria objetos DAO
	Funcionario funcionario = Funcionario();
	FuncionarioDAO inserir = FuncionarioDAO();

	// Alimenta dados ao objeto
	funcionario.setId(_wtoi(codigo));
	funcionario.setNome(pnome);
	funcionario.setSobrenome(snome);
	funcionario.setCargo(cargo);
	funcionario.setSalario(_wtof(salario));

	// Verifica resultado
	bool resultado = inserir.insereFuncionario(funcionario);

	if (resultado)
	{
		AfxMessageBox(L"Dados inseridos com sucesso!");
	}
	else
	{
		AfxMessageBox(inserir.getErro());
	}	

}

// botão Updata
void CCamposcppDlg::OnBnClickedButton4()
{
	// Recupara texto dos componentes
	m_codigo.GetWindowTextW(codigo);
	m_pnome.GetWindowTextW(pnome);
	m_snome.GetWindowTextW(snome);
	m_cargo.GetWindowTextW(cargo);
	m_salario.GetWindowTextW(salario);

	// Troca ponto decimal para o banco de dados
	int i = salario.Replace(L",", L".");

	// Cria objetos DAO
	Funcionario funcionario = Funcionario();
	FuncionarioDAO alterar = FuncionarioDAO();

	// Alimenta dados no objeto
	funcionario.setId(_wtoi(codigo));
	funcionario.setNome(pnome);
	funcionario.setSobrenome(snome);
	funcionario.setCargo(cargo);
	funcionario.setSalario(_wtof(salario));

	// Altera objeto
	bool resultado = alterar.alterarFuncionario(funcionario);

	// Verifica resultado
	if (resultado)
	{
		AfxMessageBox(L"Dados alterados com sucesso!");
	}
	else
	{
		AfxMessageBox(alterar.getErro());
	}
}

void CCamposcppDlg::OnBnClickedButton5()
{
	// Recupera dados da GUI
	m_codigo.GetWindowTextW(codigo);
	m_pnome.GetWindowTextW(pnome);
	m_snome.GetWindowTextW(snome);
	m_cargo.GetWindowTextW(cargo);
	m_salario.GetWindowTextW(salario);

	// Troca ponto decimal para o banco de dados
	int i = salario.Replace(L",", L".");

	// Cria objetos DAO
	Funcionario funcionario = Funcionario();
	FuncionarioDAO apagar = FuncionarioDAO();

	// Alimenta dados ao objeto
	funcionario.setId(_wtoi(codigo));
	funcionario.setNome(pnome);
	funcionario.setSobrenome(snome);
	funcionario.setCargo(cargo);
	funcionario.setSalario(_wtof(salario));

	// Apaga objeto
	bool resultado = apagar.deletarFuncionario(funcionario);

	// Verifica resultado
	if (resultado)
	{
		AfxMessageBox(L"Dados apagados com sucesso!");
	}
	else
	{
		AfxMessageBox(apagar.getErro());
	}
}

SAP MaxDB é um banco de dados estratégico criado para rodar em todas as soluções SAP e substituir os bancos de dados Oracle, IBM DB2 e MSSQL Server  tornando as soluções SAP mais acessíveis em termos de custo para clientes de grande e médio porte. O SAP MaxDB foi construído como uma solução open source baseado em MySQL sob a licença GNU GPL, as versão anteriores do MaxDB ainda são mantidas pela comunidade open source mas a SAP não contribui mais com estas versões.

Ao longo dos últimos anos, a tecnologia SAP MaxDB continuou a evoluir com investimentos muito significativos em inovações e essas inovações não são em código aberto. Assim o mais recente produto SAP MaxDB não é open source, entretanto ele é gratuito em sua versão comunitária para uso com aplicações não SAP e possui licença comercial para uso com aplicações SAP.

Com 40 anos de inovação atuando em mais de 130 países e com mais de 100 mil clientes que utilizam soluções SAP, o SAP MaxDB ainda é um banco de dados jovem mas conta com mais de 6.500 clientes em 15.000 instalações mais soluções que utilizam liveCache e Content Server.

SAP MaxDB: http://maxdb.sap.com/

SAP MaxDB e C++ MFC

O C++ MFC utiliza as classes de fundação Microsoft e é a linguagem padrão para se desenvolver aplicativos Desktop C++ para Windows, você precisa no mínimo de uma versão profissional do Visual Studio para utilizar este framework.

A SAP disponibiliza uma API para utilizar o MaxDB com a linguagem de programação C++ utilizando os sistemas operacionais Unix, Linux e Windows, possibilitando integrar soluções Enterprise SAP que utilizam o banco de dados MaxDB com aplicações escritas em C++ ou permite que aplicações C++ utilizem o SAP MaxDB gratuitamente também em soluções que não possuem o intuito de integrar dados com os sistemas SAP.

Softwares Requeridos

Para utilizar este walkthrough completo integrando uma solução C++ com a linguagem de programação ABAP, você precisa instalar vários software entres eles o NetWeaver Application Server ABAP no qual já possui uma instalação completa do ambiente de desenvolvimento SAP com uma instancia do banco de dados MaxDB, caso queira utilizar somente o lado C++ você pode baixar o SAP MaxDB diretamente da SAP Store:

NetWeaver Application Server ABAP: Mini SAP

Download SAP MaxDB sistemas não SAP: SAP Store

SAP MaxDB SQL Studio: Desenvolvimento Aberto walkthrough

API C++ e  Drivers ODBC

Microsoft Fundation Classes permite utilizar suas classes para conectar ao MaxDB de um modo simples através do protocolo padrão ODBC, no entanto os drivers ODBC disponibilizados pela SAP não possuem a mesma arquitetura para aplicativos win32 (código nativo)  x64, então precisamos utilizar o driver 32bit disponibilizado pelo SAP MaxDB SQL Studio.

Caso não queira utilizar as classes MFC, a instalação do SAP MaxDB incluída nos produtos SAP como o núcleo de desenvolvimento do sistema SAP R/3 chamado de NetWeaver Application Sever ABAP já comtempla uma API C++ para que você possa acessar o banco de dados MaxDB e se encontra no seguinte local:

C:\sapdb\clients\NSP\sdk\sqldbc\incl
C:\sapdb\NSP\db\doc\FirstSteps\SQLDBC

Conectando ao MaxDB NSP com C++

1 – Caso utilize este tutorial com o NetWeaver primeiro tenha certeza que servidor de aplicação e a instancia SAP do banco de dados está rodando, caso utilize apenas o MaxDb e C++ ignore este passo:

SAP - Servidor de Aplicação - e Banco de dados - NetWeaver/MaxDB

SAP – Servidor de Aplicação – e Banco de dados – NetWeaver/MaxDB

2 – Abra o SQL Studio utilizando o servidor MaxDB e o banco de dados NSP ou seu próprio banco de dados caso não utilize o sistema SAP:

NSP - NetWeaver Database

NSP – NetWeaver Database

3 – Crie uma tabela Z que significa uma tabela não SAP Standard que não será transparente no conceito do dicionário de dados do sistemas SAP para isto utilize o script logo abaixo, não se assuste para desenvolvedores não SAP isto é apenas uma tabela comum do banco de dados:

Tabela Não Transparente

Tabela Z Não Transparente

4 – Utilizaremos os drivers ODBC do SAP MaxDB SQL Studio. No painel de controle escolha ferramentas administrativas e fonte de dados ODBC de 32bit, em drivers verifique seu driver NSP:

ODBC 32bit

ODBC 32bit

5 – Crie uma nova fonte de dados do usuário escolha o driver NSP ou o driver apropriado e clique em concluir:

ODBC SQLSTUDIO

ODBC SQLSTUDIO

6 – Preencha os dados de conexão com o servidor e o banco de dados e finalize:

Dados Servidor

Dados Servidor

7 – No Visual Studio crie uma solução MFC Dialog Based e disponha na tela um Static Text, um List Control e um Button, utilize a figura abaixo para o design:

Design Time

Design Time

8 – Utilize o código abaixo para manipular dados utilizando o SAP MaxDB:

C++ - Programa

C++ – Programa

9 – Para utilizar o ABAP para ler ou gravar dados nesta mesma tabela não transparente utilizando uma Stored Procedure no MaxDB através de códigos Native SQL, utilize o link abaixo:

Stored Procedure - Abap

Stored Procedure – Abap

Programa SAP – ABAP Native SQL: MaxDB Stored Procedure parâmetros IN e OUT

 Caso conecte em um banco de dados MaxDB utilizando soluções SAP tenha em mente que você deve respeitar o conceito de dados dos sistemas SAP e verificar os termos de garantia de cada produto SAP, visto que este método ao contrario do RFC  ignora a camada de banco de dados SAP e o dicionário de dados ABAP.

Como você pode verificar na imagem acima no ambiente ABAP o valor flutuante não vem formatado por padrão como estão acostumados os desenvolvedores SAP que utilizam instruções Open SQL e o dicionário ABAP no entanto você pode utilizar campos criados no dicionário apenas para a manipulação do valor de saída da Stored Procedure neste caso você deve alinhar os tipos de dados entre as aplicações C++ e aplicações ABAP.

Exemplo:

Neste exemplo utilizamos a linguagem de programação C++ para conectar ao banco de dados SAP MaxDB em uma instancia do banco de dados do NetWeaver e integrar uma tabela não transparente que pode ser manipulada tanto do lado C++ como dentro do sistema SAP utilizando Native SQL.

SQL – SAP MaxDB

-- Cria tabela no schema SAPNSP
CREATE TABLE SAPNSP.ZFUNCIONARIO
(
            ID_FUNCIONARIO INT,
            NOME VARCHAR (30),
            SOBRENOME VARCHAR(70),
            CARGO VARCHAR(30),
            SALARIO DECIMAL(9,2)
)

-- Insere dados na tabela
Insert into SAPNSP.ZFUNCIONARIO values (1,'Steve','Gates','Programador',2550.56)
Insert into SAPNSP.ZFUNCIONARIO values (2,'Bill','Jobs','Diretor',5143.71)

CPP – arquivo h


// ConexaoSapMaxDBcppDlg.h : header file
//

#pragma once

// Inclui classe de banco de dados MFC
#include "afxdb.h"
#include "afxcmn.h"

// CConexaoSapMaxDBcppDlg dialog
class CConexaoSapMaxDBcppDlg : public CDialogEx
{

public:
	CConexaoSapMaxDBcppDlg(CWnd* pParent = NULL);	// standard constructor
	enum { IDD = IDD_CONEXAOSAPMAXDBCPP_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support


protected:
	HICON m_hIcon;

	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	
	// Cria métodos e objetos da classe
	CDatabase db;
	void conectarDB(CString dns, CString usuario, CString senha);
	afx_msg void OnBnClickedButton1();
	CListCtrl m_tabela;
};

CPP – arquivo cpp


// ConexaoSapMaxDBcppDlg.cpp : implementation file
//

#include "stdafx.h"
#include "ConexaoSapMaxDBcpp.h"
#include "ConexaoSapMaxDBcppDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CConexaoSapMaxDBcppDlg dialog


CConexaoSapMaxDBcppDlg::CConexaoSapMaxDBcppDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CConexaoSapMaxDBcppDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CConexaoSapMaxDBcppDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST1, m_tabela);
}

BEGIN_MESSAGE_MAP(CConexaoSapMaxDBcppDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, &CConexaoSapMaxDBcppDlg::OnBnClickedButton1)
END_MESSAGE_MAP()


// CConexaoSapMaxDBcppDlg message handlers

BOOL CConexaoSapMaxDBcppDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// Inicializa dialogo
	// Cria o modelo de exibição de dados
	m_tabela.SetView(LV_VIEW_DETAILS);
	m_tabela.SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_GRIDLINES);


	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CConexaoSapMaxDBcppDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

HCURSOR CConexaoSapMaxDBcppDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CConexaoSapMaxDBcppDlg::OnBnClickedButton1()
{
	// campo de dado da tabela
	CString m_campo;

	// Abre conexão
         // O SAP MAXDB requer usuário e senha em caracteres UPPERCASE
       	conectarDB(L"SAPMAXDB32", L"SAPNSP", L"PASSWORD");	

	// Cria um set de dados
	CRecordset  dados(&db);

	// Executa instrução SQL
	dados.Open(CRecordset::forwardOnly, L"Select * From SAPNSP.ZFUNCIONARIO Order by 1 DESC");
	

	// Cria item
	LVITEM lvItem;

	// cria estrutura para inserir o item
	typedef struct _LVITEM
	{
		UINT mask;
		int iItem;
		int iSubItem;
		UINT state;
		UINT stateMask;
		LPTSTR pszText;
		int cchTextMax;
		int iImage;
		LPARAM lParam;
#if (_WIN32_IE >= 0x0300)
		int iIndent;
#endif
	} LVITEM, FAR *LPLVITEM;

	// Define variaveis de itens
	int InsertItem(const LVITEM* pItem);
	int nItem;

	// Converte CString para LPTSTR atraves de um TCHAR
	TCHAR sz[1024];

	// Verifica colunas
	short nFields = dados.GetODBCFieldCount();
	int colunas = m_tabela.GetHeaderCtrl()->GetItemCount();

	// Verifica colunas
	if (colunas == 0)
	{
		// Lê metadata da tabela
		CODBCFieldInfo field;
		for (UINT i = 0; i < nFields; i++)
		{
			dados.GetODBCFieldInfo(i, field);
			m_tabela.InsertColumn(i, field.m_strName, LVCFMT_LEFT, 100);
		}

	}

	// Deleta itens do controle de lista
	m_tabela.DeleteAllItems();

	// Recupera dados da tabela
	while (!dados.IsEOF())
	{
		for (short index = 0; index < nFields; index++)
		{
			dados.GetFieldValue(index, m_campo);

			// Retorna linha do banco de dados
			if (index == 0)
			{
				// Insere linha
				lvItem.mask = LVIF_TEXT;
				lvItem.iItem = 0;
				lvItem.iSubItem = 0;
				lvItem.pszText = lstrcpy(sz, m_campo);
				nItem = m_tabela.InsertItem(&lvItem);
			}

			// Retorna colunas da linha
			m_tabela.SetItemText(nItem, index, lstrcpy(sz, m_campo));

		}
		// Move o cursor para a proxima linha
		dados.MoveNext();
	}

	// Fecha o set de dados e a conexão
	dados.Close();
	db.Close();

	
}

void CConexaoSapMaxDBcppDlg::conectarDB(CString dns, CString usuario, CString senha)
{
	// Cria string de conexão ODBC
	CString conexao;

	// Cria string de conexão
	conexao = L"DSN=" + dns + L";UID=" + usuario + L";PWD=" + senha;

	// Abre conexão
	db.OpenEx(conexao, 0);
}

O termo Enterprise se refere a organização empresarial corporativa. Na indústria de computadores, o termo é frequentemente usado para descrever qualquer grande organização que utiliza computadores, sistemas operacionais, softwares ou ferramentas de desenvolvimento para o mundo dos negócios. E ao analisarmos o DNA das soluções Enterprise que encontramos nos dias de hoje, sem duvida encontraremos a herança de uma empresa que foi amplamente responsável por tudo que conhecemos, a IBM, empresa pioneira no desenvolvimento de hardware e softwares corporativos.

O principal software corporativo é chamado de Enterprise Resource Planning (ERP) e grande parte de toda infraestrutura e metodologias existentes no universo corporativo prezam garantir que este software funcione perfeitamente desde o inicio da era da computação empresarial. O ERP nasceu de seu antecessor, Manufacturing Resource Planning (MRP) e evoluiram desde os primórdios dos pacote de gerenciamento de banco de dados comercial desenvolvido por Gene Thomas na IBM na década de 1960. Logo os primeiros sistemas ERP foram concebidos como uma ferramenta organizacional e de programação para as empresas industriais. A função da próxima geração de sistemas de software ERP foram estendidos além dos limites do que poderia ser feito para uso interno de uma empresa de fabricação individual e começou a incluir clientes e fornecedores. Não demorou muito para que outras indústrias reconhecessem os benefícios dos sistemas ERP, então as agências governamentais e organizações do setor de serviços também começaram a tirar proveito desta tecnologia.

A evolução se deu dos processos executados em grandes mainframes, como IBM/360 para os processos atuais que gerenciam enormes quantidades de dados em tempo real e são executados em diferentes plataformas transpondo os limites físicos das empresas, permitindo que o processo de trabalho continue sem fronteiras e a qualquer hora, em qualquer lugar.

De onde vem os softwares Enterprise?

Um rápido passeio pela historia das três maiores soluções Enterprise encontradas no mercado de software da atualidade, nos mostram o como foi o inicio dos sistemas corporativos:

A SAP AG criada em 1972 por cinco consultores da IBM que perceberam a possibilidade de criar um pacote de software padrão a ser executado em um mainframe IBM. Em dezoito meses foi criado o sistema R que foi renomeado para R/1, sendo seguido pelo sistema R/2 de duas camadas e logo depois o R/3 apareceu inicialmente no final dos anos 80 quando a IBM lançou sua arquitetura SNA, mas foi decidido trabalhar com Unix no lugar do mainframe IBM e após cinco anos de desenvolvimento, em 1992 o sistema R/3 finalmente foi lançado.

A JD Edwards World Solution Company, foi fundada em março 1977 e era uma empresa de software empresarial, o foco inicial da empresa foi o desenvolvimento de um programa de contabilidade necessário para seus clientes. Seu produto mais popular chamado World era centralizado em servidores, bem como multiusuário; os usuários poderiam acessar o sistema usando um dos vários terminais de computador da IBM ou “telas verdes”. Como um sistema ERP, o JD Edwards World incluía as três áreas básicas de atuação: analista funcional/negócios, desenvolvedor/programador e  administração do sistema.

O Microsoft Dynamics AX foi originalmente desenvolvido como uma colaboração entre a IBM e a dinamarquesa Damgaard Data que resultou no IBM Axapta. O Axapta foi inicialmente lançado em março de 1998, nos mercados dinamarqueses  e norte-americanos. A IBM devolveu todos os direitos sobre o produto para a Damgaard Data logo após o lançamento da versão 1.5 antes da Damgaard Data ser fundida com Navision Software A/S em 2000, a empresa combinada, inicialmente Navision Damgaard, depois Navision A/S, foi adquirida pela Microsoft em julho de 2002 e em setembro de 2011, a Microsoft anunciou o lançamento da versão nova AX 2012.

Hoje a IBM não possui uma solução de ERP mas ela endossa através de suas alianças poderosas soluções em conjunto com a SAP e Oracle:

IBM ERP Alliance: http://www.ibm.com/solutions/alliance/us/en/index/erp.html

????????????????????????????????????????
O que os Softwares Corporativos Podem Fazer?

Unificar os dados como um todo, integrando os sistemas de gestão empresarial, permitindo a centralização de todo o negócio em uma única fonte, pois são desenvolvidos para atender às necessidades das diferentes áreas de uma empresa.

As varias ferramentas oferecem aos seus gestores um maior controle sobre suas operações e planejamentos, interligando todos os departamentos e se tornando um importante apoio às decisões estratégicas da diretoria, indicando os mercados mais lucrativos no qual pode-se investir.

Como beneficio a empresa passa a obter maior agilidade aos processos e uma maximização de resultados a longo prazo, com a padronização das informações internas consegue-se uma ampla visibilidade dos procedimentos empresariais e uma automação das dinâmicas de apoio. A obtenção de dados em tempo real, possibilita a eliminação das falhas de comunicação entre os setores e um melhor gerenciamento de qualidade de seus produtos ou serviços e também um melhor relacionamento com os seus clientes.

Como é a arquitetura de um software Enterprise?

Os softwares Enterprise geralmente utilizam o topo da tecnologia disponível em termos de hardware. Novos hardwares são construídos para atender as novas exigências que as empresas demandam com o crescimento baseado no beneficio da tecnologia que elas adquirem, sendo assim novos hardwares necessitam de novas versões de softwares e sistemas operacionais para que possam ser controlados, gerando um ciclo de desenvolvimento de tecnologia de ponta.

Os programas Enterprise atuais utilizam uma arquitetura de três camadas, cada camada é auto contida o suficiente de forma que a aplicação pode ser dividida em vários computadores em uma rede distribuída. As camadas são compostas da interface do usuário (Camada de Apresentação ou Servidor de Apresentação); da lógica do negócio (Camada de Negócio ou Servidor de Aplicação) e da camada de banco de dados (Camada de Dados ou Servidor de Dados). Cada camada desta arquitetura é normalmente mantida em um ou mais servidores para tornar-se mais escalonável e independente das demais. Com o mesmo objetivo são utilizadas tecnologias de middleware como, por exemplo, COM, CORBA, Web Services ou RMI. Esta arquitetura tem como características baixos custos de disponibilização, de mudança da base de dados, de mudança na lógica de negócios, eficiente armazenamento e reutilização de recursos.

Três camadas SAP:

R/3 - Três camadas

R/3 – SAP – Três camadas

Três camadas Oracle:

JD Edwards - três camadas

JD Edwards – Oracle – Três camadas

Três camadas Microsoft:

Dynamics - Microsoft - Três camadas

Dynamics – Microsoft – Três camadas

Como funcionam na pratica para desenvolvedores e consultores?

Os softwares corporativos que integram a linha empresarial como já vimos ditam não só a tecnologia de hardware e software mas também o funcionamento de empresas de tecnologia, de desenvolvimento ou consultorias que trabalham com este tipo de solução.

No mercado de softwares corporativos um desenvolvedor em alguns casos também é um tipo de consultor ou especialista, outras profissões que conhecemos no mercado da tecnologia também se enquadram no time de consultores tendo sua própria nomenclatura, os códigos fontes são abertos e podem ser herdados e modificados, porem geralmente tudo que é desenvolvido dentro de um software corporativo pela licença sob o qual ele é gerido é de propriedade da empresa fabricante do software, entretanto é permitindo que consultorias desenvolvam e comercializem módulos adicionais para seus produtos seguindo as melhores praticas de desenvolvimento, implantação e manutenção da empresa detentora da solução.

Os sistemas ERP podem se conectar com qualquer banco de dados topo de linha do mercado e tem como parceiros as empresas fabricantes de cada banco, quando também não é proprietária de uma solução de banco de dados, em ambos os casos os bancos de dados possuem Features exclusivas desenvolvidas para uso com cada um destes sistemas. Os sistemas ERP contam com um dicionário de dados que controla o banco de dados em uso, permitindo que o sistema e os desenvolvedores utilizem uma linguagem única para acesso a dados. Possuem também seu próprio compilador e sua própria linguagem de programação na qual as consultorias podem desenvolver novos módulos ou modificar módulos existentes.

A SAP possui a linguagem Abap, a Oracle utiliza entre outros métodos a linguagem C e a Microsoft a linguagem X++. As empresas terceirizadas também podem desenvolver outros softwares corporativos que se comunicam com o ERP através de um protocolo de comunicação especifico, geralmente utilizando as tecnologias DCOM ou Corba e são nada mais que interfaces para a comunicação entre um sistema proprietário e outro compatível de terceiros através de conexões TCP/IP e podem chamar funções remotas do ERP que são criadas para inserir ou exportar dados garantindo a consistência de dados utilizando a própria regra de negocio do ERP e fornecendo uma maneira para que um programa externo escrito em linguagens como  Java, C, C ++C# ou outras línguas possam também atuar como o cliente ou servidor em uma chamada.

SAP – Abap: Linguagem de programação.

Oracle – JDE: Development Tools.

Microsoft – MorphX: IDE e linguagem X++.

Solutions_key
Como é a Metodologia dos Softwares Enterprise?

Com décadas de experiência no mercado corporativo os softwares empresariais desenvolveram algumas metodologias ao longo dos anos que possibilitam que as empresas utilizem de forma adequada suas soluções, abrangendo todas as fases de um projeto desde a engenharia de software, a definição de escopo, passando pela especificação funcional, design, construção, testes, até chegar à validação, implantação e uso produtivo da solução.

ASAP Methodology: Metodologia ASAP

Oracle Unified Method: Metodologia OUM

Microsoft Dynamics Sure Step methodology: Metodologia MS Sure Step

Falando de modo genérico já que estamos nos referindo a três ótimos softwares empresariais da atualidade, podemos perceber que os três possuem uma arquitetura semelhante que proporciona uma metodologia muito similar para execução de seus projetos, deste modo, segue uma visão geral de um projeto corporativo.

A fase de preparação geralmente é executada por um gerente de projetos e engloba o escopo, estimativas, planejamento inicial do projeto, cronograma, aspectos técnicos, definição de equipe, identificação de riscos e estratégias, planejamento de controle de qualidade e o inicio do projeto.

A fase inicial, já com os recursos definidos em ação, o gerente de projeto e os analistas funcionais devem tratar do levantamento dos processos de negócio, gestão do projeto, mudanças organizacionais, definição dos novos processos de negócio, necessidades e mudanças organizacionais.

Com toda a definição realizada, já na fase de customização e desenvolvimento, entra em cena os consultores especialistas que iniciam a configuração, implementação e o desenvolvimento das definições funcionais que entre elas estão a configuração base, a configuração final, desenvolvimento de programas, implementação de interfaces, testes unitários, testes integrados, documentação de cenários e processos, execução dos treinamentos aos key users e usuários, controle de qualidade e a correção de possíveis erros.

Na fase de pré-produção toda atenção se volta aos detalhes finais como, testes de volume, testes de stress, planejamento da implantação, estratégia de implantação, treinamentos finais e o controle de qualidade.

Com tudo pronto o projeto é finalmente implantado e o sistema é colocado em produção e os retoques finais são a transferência de pré-produção, ajuste da configuração de hardware, ajustes na configuração de software, base de dados, sistema operacional e outros. Só então se inicia os treinamentos finais, suporte aos key-users e usuários e encerramento do projeto.

Ambientes Corporativos

Integrando a metodologia de gestão de projeto os softwares corporativos e suas demais ferramentas são desenvolvidas para utilizar ambientes específicos nos quais tem o intuito de maximizar a eficiência dos métodos de implantação, desenvolvimento, testes, qualidade, treinamento, utilização e gerenciamento dos produtos adquiridos. Cada ambiente possui suas especificações de uso e são utilizados para uma finalidade especifica e devido a eficiência deste modelo outras metodologias também utilizam alguns destes cenários.

Ambientes do SAP:

Alguns dos ambientes SAP

Alguns dos ambientes SAP

Ambientes da Oracle:

Alguns dos ambientes Oracle

Alguns dos ambientes Oracle

Ambientes da Microsoft:

Alguns dos ambientes Microsoft

Alguns dos ambientes Microsoft

Como Desenvolver Suas Próprias Aplicações Enterprise?

As grandes empresas de tecnologia que desenvolvem o hardwaresoftware para o mercado corporativo em sua maioria também desenvolvem ferramentas para desenvolvimento de softwares para empresas terceirizadas, para que estas possam desenvolver seus próprios softwares empresariais ou soluções que complementas as soluções já existentes, entre elas a Oracle, a IBM, a Microsoft e com exceção da SAP que também utilizam em certos casos o Java da Oracle e ferramentas da IBM como a IDE Eclipse. Todas disponibilizam um vasto matérial sobre como desenvolver seus próprios projetos Enterprise, veja os seguintes links:

Microsoft: http://msdn.microsoft.com/en-us/library/ff648951.aspx

Oracle: http://www.oracle.com/technetwork/java/javaee/overview/index.html

IBM: http://www.ibm.com/developerworks/

SAP: Enterprise Learning

O primeiro passo é ter em mente que um software enterprise bem sucedido necessita de hardware adequado, arquitetura e programação adequada, metodologia adequada, consultoria adequada e o mais importante de tudo um grande know-how das regras de negocio das áreas incluídas no escopo de sua solução.

Para utilizar senhas em um campo de edição na linguagem de programação C++ você deve usar o componente LineEdit com sua propriedade echoMode alterada para Password, deste modo o controle altera a visualização dos caracteres comuns para caracteres “*”.

E para exibir um resultado ou mensagem para o usuário você pode utilizar a classe QMessageBox, está fornece uma caixa de diálogo modal para informar o usuário ou para fazer ao utilizador uma pergunta e receber uma resposta.

Campo de senha e Caixa de Menssagem

Campo de senha e Caixa de Menssagem

Qt Creator Design

1 – Crie um projeto no Qt e adicione na tela um Label, um LineEdit e um PushButton, alinhe e mude as propriedades de texto dos widgets como na figura abaixo.

Design

Design

Altere a propriedade do LineEdit chamada echoMode para Password e utilize o código abaixo para completar seu código gerado automaticamente, atente-se que declaramos um método para verificação da senha na definição da classe no arquivo .h e o utilizamos na implementação da classe no arquivo .cpp.

Exemplo:

Neste exemplo criamos um método para verificar a senha no qual o usuário entrará através de uma caixa de edição, será verificado primeiro o tamanho da senha e logo após o conteúdo da senha, visto que este método não pode ser utilizado em um programa funcional, limita-se apenas para o aprendizado de como utilizar mascaras de senha no widget LineEdit e não como trabalhar com senhas em nível profissional.

Para a versão deste programa para C++ Windows MFC: clique aqui.

C++

Classe – arquivo .h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;

    // Cria metodo de verificação de senha
    bool verificaSenha(QString senha);
};

#endif // MAINWINDOW_H

Classe – arquivo .cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

bool MainWindow::verificaSenha(QString senha)
{
    // campo para validar função
    bool correto = true;

    // recupera senha de alguma fonte (apenas teste)
    QString recSenha = "daaberto";

    if ((senha.length() != recSenha.length()) || (senha != recSenha))
    {
        correto = false;
    }

    return correto;
}

void MainWindow::on_pushButton_clicked()
{
    // Verifica senha e exibe resultado

   if (verificaSenha(ui->lineEdit->text()))
   {
       QMessageBox::information(this, tr("Sucesso"),tr("\nSenha verificada com sucesso!\n"));
   }
   else
   {
       QMessageBox::information(this, tr("Erro"),tr("\nSenha invalida, tente outra vez!\n"));
   }
}

Qt – Context Menu – C++ – Linux

Publicado: 5 de outubro de 2014 em C/C++

Um menu de contexto ou um menu pop-up é um menu em uma interface gráfica do usuário (GUI) que aparece em cima de interação do usuário, como uma operação de clique com o botão direito do mouse. Um menu de contexto oferece um conjunto limitado de opções que estão disponíveis no estado atual, ou contexto, do sistema operacional ou aplicativo. Normalmente, as opções disponíveis são as ações relacionadas com o objeto selecionado.

Os menus de contexto foram introduzidos no ambiente Smalltalk do computador Xerox Alto, onde eram chamados menus pop-up. O sistema operacional NEXTSTEP desenvolveu a ideia, incorporando a funcionalidade em que o botão do meio ou o da direita traziam o menu principal na posição do mouse, eliminando a necessidade de mover o ponteiro por toda a tela. Esse menu principal era vertical e mudava de acordo com o texto da operação do sistema.

Menu de Contexto ou Popup Menu

Menu de Contexto ou Popup Menu

Qt Creator – Design

Um menu de contexto em Qt necessita de três elementos básicos são eles: signals, slots e actions, para criar um menu de contexto siga os seguintes passos.

1 – Crie um novo projeto C++ Qt com Widgets e arraste para o formulário, dois componentes Labels e um componente ListWidget e mude suas propriedades de texto e alinhe os Widgets como na figura abaixo:

Qt - Creator - Design

Qt – Creator – Design

2 – Clique no componente ListWidget e mude sua propriedade contextMenuPolicy para CustomContextMenu, agora na aba Signals/Slots Editor adicione um novo Signal para o componente ListWidget com o sinal customContextMenuRequest(QPoint), logo após clique novamente no componente ListWidget e crie um novo Slot para o método customContextMenuRequest(QPoint), utilize a imagem abaixo para referencia:

Signals/Slots

Signals/Slots

3 – Vamos agora criar a ação para o item do menu que acabamos de criar, para isto clique na aba Action Editor e crie uma nova ação e um novo slot para a ação para executar o método chamado triggered():

Action - Menu

Action – Menu

4 – Utilize o código abaixo para completar o código gerado automaticamente e rode o programa.

Exemplo:

Neste exemplo criamos um Signal e um Slot para o componente ListWiget no qual receberá um menu de contexto e também criamos uma ação para que seja executado a opção desejada do menu.

Para a versão deste programa para C++ Windows MFC: clique aqui.

C++

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
    // Inicializa lista de opções
    // Adiciona Musicas do album Ten (Pearl Jam)
    QString  musicas[] = {"Once",  "Even Flow", "Alive", "Why Go", "Black",
                         "Jeremy", "Oceans", "Porch", "Garden", "Deep",
                         "Release"};
    for (int i = 0; i < 11; i++)
    {
        ui->listWidget->addItem(musicas[i]);
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}


// Declara Slot para exibir menu de contexto
void MainWindow::on_listWidget_customContextMenuRequested(const QPoint &pos)
{
    QMenu contextMenu(tr("Context menu"), this);

    // Adiciona ação ao menu de contexto
    contextMenu.addAction(ui->actionEscolher_est_M_sica);

    // Cria mais itens sem ações (estetica)
    contextMenu.addAction(new QAction(tr("Item 1"), this));
    contextMenu.addAction(new QAction(tr("Item 2"), this));
    contextMenu.addAction(new QAction(tr("Item 3"), this));
    contextMenu.exec(mapToGlobal(pos));

}

// Declara slot para a ação do item do menu
void MainWindow::on_actionEscolher_est_M_sica_triggered()
{
   ui->label_2->setText("Você clicou na opção: " + ui->listWidget->currentItem()->text());
}

 

 

Qt – Menu – C++ – Linux

Publicado: 4 de outubro de 2014 em C/C++

Em computação um menu é uma lista de opções ou comandos apresentados a um operador por um computador. Os menus são, por vezes, hierarquicamente organizado, permitindo uma navegação através de diferentes níveis da estrutura do menu.  A seleção de um item do menu com uma seta irá expandi-lo, mostrando um segundo menu (o sub menu) com opções relacionadas com a entrada selecionada. É possível adicionar outros componentes ao menu como ícones de imagem, um componente de botões de radio e até mesmos botões de cheque. O menu em alguns sistemas operacionais são localizados na barra de titulo/tarefas no topo do sistema e não no próprio aplicativo.

Qt - Menu

Qt – Menu

Qt Creator – Design

1 – Crie um novo projeto de Widget do Qt, você pode perceber que os componentes Menu, Barra de tarefas e a barra de status já são criados por padrão. Neste primeiro momento vamos utilizar apenas o Widget menu. Você pode clicar diretamente no item do menu e criar os menus digitando os nomes da opções que você precisa, use a figura abaixo para o design do seu menu:

Criando Menu

Criando Menu

2 – Coloque dois Labels no formulário e mude suas propriedades de texto como na imagem do programa logo acima . Para criar os Slots para os eventos de clique do menu você precisa utilizar a aba Action Editor que esta localizada abaixo da área de edição do seu formulário. Clique em cada ação e com o botão direito do mouse escolha a opção Go to Slot:

Menu Actions - Slots

Menu Actions – Slots

Utilize o código abaixo para preencher o código gerado automaticamente e clique em RUN para rodar o programa.

Exemplo:

Neste exemplo criamos o menu em Design Time e criamos um Slot para cada ação do menu, as ações serão responsáveis por nos dizer qual menu foi clicado utilizando um componente Label no centro do formulário.

Para a versão deste programa para C++ Windows MFC: clique aqui.

C++

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_actionMenu_1_triggered()
{
   ui->label_2->setText("Você clicou no: Menu opção 1");
}

void MainWindow::on_actionMenu_2_triggered()
{
   ui->label_2->setText("Você clicou no: Menu opção 2");
}

void MainWindow::on_actionMenu3_triggered()
{
    ui->label_2->setText("Você clicou no: Menu opção 3 Sub Menu opção 1");
}
void MainWindow::on_actionMenu_4_triggered()
{
    ui->label_2->setText("Você clicou no: Menu opção 4");
}

 

Qt – Horizontal Slider – C++ – Linux

Publicado: 4 de outubro de 2014 em C/C++

Um Slider é um controle deslizante, também conhecido como Track Bar, é um objeto de interface gráfica (GUI) com o qual o usuário pode definir um valor movendo um indicador, geralmente de uma forma horizontal. Em alguns casos, o usuário também pode clicar em um ponto no controle deslizante para alterar a configuração.

Horizontal Slider - Programa

Horizontal Slider – Programa

Qt Creator – Design

Crie um novo projeto C++ utilizando Widgets e arraste para o formulário três componentes Labels, um componente Horizontal Slider e um PushButton, crie um Slot de mudança de valor para o Slider, um Slot de clique para o PushButton. Use a figura abaixo para a criação do design:

Design

Design

Exemplo:

Neste exemplo criamos um programa que exibe o valor de um Slider em um controle Label através do evento de mudança de valor do Slider e também do clique de um botão.

Para a versão deste programa para C++ Windows MFC: clique aqui.

C++

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_horizontalSlider_valueChanged(int value)
{
    ui->label_2->setText("Valor do Slider: " + QString::number(ui->horizontalSlider->value()));
}

void MainWindow::on_pushButton_clicked()
{
    ui->label_3->setText("Clique no botão para selecionar um valor: " +
                          QString::number(ui->horizontalSlider->value()));
}

Qt – SpinBox- C++ – Linux

Publicado: 4 de outubro de 2014 em C/C++

SpinBox

É um controle de rotação, onde os usuários podem clicar em botões de seta para alterar gradualmente o valor dentro de sua caixa de texto numérico . A caixa de rotação refere-se à combinação de uma caixa de texto e seu controle de rotação associado. O SpinBox possui uma faixa de configuração de valore limite permitindo que o usuário escolha valores entre o mínimo e o máximo definido pelo desenvolvedor.

SpinBox - Programa

SpinBox – Programa

Qt Creator – Design

Crie um novo programa C++ utilizando Widgets e arraste para a tela três Labels, um LineEdit, um SpinBox e um PushButton. Crie o Slot para o evento de clique do botão e utilize o código abaixo para completar o código gerado automaticamente. Use a figura abaixo para auxiliar o design do formulário:

Qt -Design

Qt -Design

Exemplo:

Neste exemplo usamos um SpinBox e o associamos a um LineEdit Control e inicializamos o SpinBox, parametrizando um valor mínimo e um valor máximo para o controle.

Para a versão deste programa C++ Windows MFC: clique aqui.

C#

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // Inicializa valores limite para o SpinBox
    ui->spinBox->setRange(1,10);

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    // captura e exibe texto do SpinBox
     ui->lineEdit->setText(ui->spinBox->text());
}

ComboBox

Em computação, uma caixa de combinação é um elemento de interface gráfica. Um ComboBox permite ao usuário escolher uma das várias opções, pode ter duas formas muito diferentes. A forma padrão é a caixa de combinação não editável, que conta com um botão e uma lista suspensa de valores. A segunda forma, chamada de caixa de combinação editável, possui um campo de texto com um pequeno botão confinando-o. O usuário pode digitar um valor no campo de texto ou clique no botão para exibir uma lista drop-down.

Listwidget

Em computação, uma caixa de listagem é um elemento de interface gráfica. Uma ListBox apresenta ao usuário um grupo de itens, exibidos em uma ou mais colunas. As listas podem ter muitos itens, por isso eles são muitas vezes colocados em painéis de rolagem.

ComboBox - ListWidget - Programa

ComboBox – ListWidget – Programa

Qt Creator

Para criar um programa como este você precisa aprender alguns pequenos detalhes da interface gráfica e algumas das peculiaridades dos widgets do framework Qt, então siga os seguintes passos:

1 – Crie um novo projeto de Widgets. Arraste para o formulário um componente GroupBox e o redimensione para que caiba todos os outros componentes dentro dele. Você pode notar que o componente está sem as bordas, isto se deve ao fato de que os widgets do Qt são customizáveis e possuem a propriedade StyleSheet para que você possa declarar as modificações que deseja na aparência de cada componente. Abra a propriedade StyleSheet e na janela subsequente e coloque o código como na imagem abaixo:

Qt - StyleSheet

Qt – StyleSheet

Sobre Qt StyleSheets: http://qt-project.org/doc/qt-4.8/stylesheet.html

2 – Arraste para a tela 3 widgets Label, um ListWidget e um combobox, mude suas propriedades de texto e os alinhe conforme a figura abaixo:

Qt Creator - Design

Qt Creator – Design

3 –  Após terminar o design crie os Slots de duplo clique para o ListWidget e o de mudança de item para o ComboBox, utilize o código abaixo para completar o seu código gerado automaticamente, visto que utilizamos o construtor da classe para inicializar uma Array com os dados que utilizaremos para os componentes. Clique em Run para rodar o programa.

Para a versão deste programa C++ Windows MFC: clique aqui.

Exemplo:

Neste exemplo usamos um ComboBox e um ListBox para criar um programa C++ e utilizamos os slots para os eventos de cada Widget para interligar suas ações.

C++

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // Inicializa formulario

    // Cria Array
    QString  itens[] = { "Satisfaction", "Paint it Black", "Wild Horses", "Brown Sugar",
                         "Sympathy for the Devil", "Start Me Up" };

    // Alimenta ListBox e Combobox
    for (int i=0; i < 6; i++)
    {
        ui->listWidget->addItem(itens[i]);
        ui->comboBox->addItem(itens[i]);
    }

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_listWidget_doubleClicked(const QModelIndex &index)
{
    // Alimenta texto e Sincroniza combo
    ui->label->setText("Rolling Stones: " + ui->listWidget->currentItem()->text());
    ui->comboBox->setCurrentIndex(ui->listWidget->currentIndex().row());
}

void MainWindow::on_comboBox_currentIndexChanged(const QString &arg1)
{
     // Alimenta texto e Sincroniza lista
     ui->label->setText("Rolling Stones: " + ui->comboBox->currentText());
     ui->listWidget->setCurrentRow(ui->comboBox->currentIndex());
}

Qt – RadioButton – isChecked – C++ – Linux

Publicado: 2 de outubro de 2014 em C/C++

RadioButton

Em computação, um botão de opção ou botão de rádio (Radiobutton) é um elemento de interface gráfica (isto é um componente widget) com dois estados: selecionado (ativado) e não-selecionado (desativado), quando o usuário pressiona um botão do mouse ou uma tecla como espaço. Botões de opção são usados num grupo para apresentar um conjunto limitado de escolhas (duas ou mais) que são mutuamente exclusivas. Deste maneira, quando o usuário seleciona um outro botão no mesmo conjunto, o outro botão já selecionado torna-se automaticamente desativado.

isChecked

É uma função que retorna um valor equivalente ao Checked (marcado) em linguagens de alto nível.

Programa - C++

Programa – C++

Qt Creator – Design

Escolha um novo projeto Qt Widget Application e adicione ao formulário um 3 Labels, 4 Radiobuttons, 2 LineEdits, 1 TextEdit e um botão. Mude as propriedades de cada componente de acordo com sua preferencia, crie um Slot para cada evento de clique de cada respectivo Widget. Use a imagem abaixo para referencia do design.

Qt Creator - Design

Qt Creator – Design

Exemplo:

Neste exemplo criamos um grupo de botões de radio que efetua as 4 operações básicas da matemática, usando o evento de item e a verificação do seu estado, neste primeiro exemplo você pode ver que utilizamos as conversões de valores básicas entre os tipos para efetuar os cálculos do programa.

Para a versão deste programa C++ Windows MFC: clique aqui.

C++

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

// Slots para os cliques dos botões de radio
void MainWindow::on_radioButton_clicked()
{
    // Verifica estado do botão de radio
    if (ui->radioButton->isChecked())
    {
        ui->textEdit->insertPlainText("Soma:\n");
    }
}

void MainWindow::on_radioButton_2_clicked()
{
    if (ui->radioButton_2->isChecked())
    {
        ui->textEdit->insertPlainText("Subtração:\n");
    }
}

void MainWindow::on_radioButton_3_clicked()
{
    if (ui->radioButton_3->isChecked())
    {
        ui->textEdit->insertPlainText("Multiplicação:\n");
    }
}

void MainWindow::on_radioButton_4_clicked()
{
    if (ui->radioButton_4->isChecked())
    {
        ui->textEdit->insertPlainText("Divisão:\n");
    }
}

// Slot de clique do botão
void MainWindow::on_pushButton_clicked()
{
    // O calculo poderia ser efetuado em uma unica linha de instruções
    // ṕorem para ficar mais facil de ler preferimos desmenbra-lo
    // você pode modificar o calculo deixando o programa menor
    
    
    // Variavel para o calculo
    double valor;

    if (ui->radioButton->isChecked())
    {
        // Efetua o calculo
        valor = ui->lineEdit->text().toDouble() + ui->lineEdit_2->text().toDouble();
        ui->textEdit->insertPlainText(ui->lineEdit->text() + " + " + ui->lineEdit_2->text() +
                                      " = " +QString::number(valor)+"\n"); // Converte valores
    }

    if (ui->radioButton_2->isChecked())
    {
        valor = ui->lineEdit->text().toDouble() - ui->lineEdit_2->text().toDouble();
        ui->textEdit->insertPlainText(ui->lineEdit->text() + " - " + ui->lineEdit_2->text() +
                                      " = " +QString::number(valor)+"\n");
    }

    if (ui->radioButton_3->isChecked())
    {
        valor = ui->lineEdit->text().toDouble() * ui->lineEdit_2->text().toDouble();
        ui->textEdit->insertPlainText(ui->lineEdit->text() + " * " + ui->lineEdit_2->text() +
                                      " = " +QString::number(valor)+"\n");
    }

    if (ui->radioButton_4->isChecked())
    {
        valor = ui->lineEdit->text().toDouble() / ui->lineEdit_2->text().toDouble();
        ui->textEdit->insertPlainText(ui->lineEdit->text() + " / " + ui->lineEdit_2->text() +
                                      " = " +QString::number(valor)+"\n");
    }
}