Redes Neurais Artificiais (Adaline, Algoritmos e Considerações Finais) - Parte 03

17. maio 2013 11:07 by BBranquinho in Java, Redes Neurais Artificiais  //  Tags: , ,   //   Comentários (0)

Aew meus amigos Nerds.

Neste post finalizo a apresentação do tema Redes Neurais Artificiais. Em especial trata da rede Adaline, descrevo os algoritmos e faço uma consideração final sobre o que foi apresentado. O vídeo abaixo mostra com detalhes os tópicos citados.

Para realizar o treinamento da rede Adaline usamos o algoritmo Eqm para realizar o cálculo do erro. Abaixo temos este algoritmo.

package org.wpattern.redes.neurais.artificiais.capitulo4;

/**
 * Algoritmo implementado tendo como base o pseudocodigo apresentado no
 * livro "Redes Neurais Artificiais para engenharia e ciencias aplicadas"
 * do autor Ivan Nunes da Silva.
 * 
 * Capitulo 4.3.
 * 
 * @author Augusto Branquinho
 */
public class Eqm {

	public static double calculateEQM(double[][] amostras, double[] saidas, double[] pesos) {
		// 1. Obtendo a quantidade de padroes de treinamento.
		int quantidadePadroes = saidas.length;

		// 2. Inicializando a variavel EQM.
		double eqm = 0.0;

		// 3. Para cada amostra de treinamento realizamos o calculo
		// de "u" e posteriormente o calculo do somatorio do EQM.
		for (int k = 0; k < quantidadePadroes; k++) {
			// 3.1. Multiplicar o peso por uma dada amostra.
			// Pode ser usado um vetor para guardar os resultados.
			// Contudo, achei mais facil ja fazer a soma diretamente.
			double u = 0.0;

			for (int linha = 0; linha < amostras.length; linha++) {
				u += pesos[linha] * amostras[linha][k];
			}

			// 3.2. Realizado o calculo do EQM.
			eqm += Math.pow(saidas[k] - u, 2.0);
		}

		// 3. Calculado da media do EQM.
		double eqmMedio = eqm / quantidadePadroes;

		return eqmMedio;
	}

}

Para realizar o treinamento da rede para encontrar os pesos temos o algoritmo a seguir.

package org.wpattern.redes.neurais.artificiais.capitulo4;

import java.util.Random;

/**
 * Algoritmo implementado tendo como base o pseudocodigo apresentado no
 * livro "Redes Neurais Artificiais para engenharia e ciencias aplicadas"
 * do autor Ivan Nunes da Silva.
 * 
 * Capitulo 4.3.
 * 
 * @author Augusto Branquinho
 */
public class AdalineTraining {

	public static void main(String[] args) {
		AdalineTraining treinamento = new AdalineTraining();

		double[][] amostras = new double[][] {
				{-1.0, -1.0, -1.0, -1.0 },
				{ 0.1,  0.3,  0.6,  0.5 },
				{ 0.4,  0.7,  0.9,  0.7 },
				{ 0.7,  0.2,  0.8,  0.1 }};

		double[] saidas = new double[] { 1.0, -1.0, -1.0, 1.0 };

		double[] pesos = treinamento.executarFaseTreinamento(amostras, saidas);

		String formatoVetor = "{ ";
		for (int i = 0; i < pesos.length; i++) {
			System.out.println(String.format("Peso final %s = %s", i, pesos[i]));
			formatoVetor += pesos[i] + (((i + 1) != pesos.length) ? ", " : "");
		}
		formatoVetor += " }";
		System.out.println(formatoVetor);
	}

	public double[] executarFaseTreinamento(double[][] amostras, double[] saidas) {
		Random random = new Random(System.currentTimeMillis());

		// 1. Conjunto de amostras de testes dadas como entrada. x^(k)

		// 2. Saidas das amostras dadas como entrada.

		// 3. Realizar o sorteio dos pesos aleatoriamente.
		double[] pesos = new double[saidas.length];

		for (int i = 0; i < pesos.length; i++) {
			pesos[i] = 1.0 / (random.nextInt(100) + 1.0);
		}

		// 4. Especificando a taxa de aprendizagem e precisao requerida.
		double taxaAprendizado = 0.05;
		double precisao = 0.0000;

		// 5. Iniciando o contador de epocas.
		int epoca = 0;

		// 6. Repetir as instrucoes equanto o erro estiver fora da precisao requerida.
		double eqmAnterior, eqmAtual;

		do {
			// 6.1. Calcular o EQM com os pesos atuais.
			eqmAnterior = Eqm.calculateEQM(amostras, saidas, pesos);

			// 6.2. Para todas as amostras de treinamento {x^(k), d^(k)}.
			for (int k = 0; k < amostras.length; k++) {
				// 6.2.1. Multiplicar o peso por uma dada amostra.
				// Pode ser usado um vetor para guardar os resultados e depois realizar a soma.
				// Contudo, achei mais facil ja fazer a soma diretamente.
				double u = 0.0;

				// A inversao das variaveis i e k corresponde a transposta da matriz.
				for (int i = 0; i < pesos.length; i++) {
					u += pesos[i] * amostras[i][k];
				}

				// 6.2.2. é realizado o ajuste de pesos e marcamos que existe erro.
				for (int i = 0; i < pesos.length; i++) {
					pesos[i] = pesos[i] + taxaAprendizado * (saidas[k] - u) * amostras[i][k];
				}
			}

			// 6.3. Incremento da epoca.
			epoca++;

			// 6.4. Calculamos oo EQM dos pesos atuais.
			eqmAtual = Eqm.calculateEQM(amostras, saidas, pesos);
		} while (Math.abs(eqmAtual - eqmAnterior) > precisao);

		System.out.println("Epoca " + epoca);

		return pesos;
	}

}

Para finalizar o algoritmo que realiza a classificação de acordo com uma amostra temos:

package org.wpattern.redes.neurais.artificiais.capitulo4;


/**
 * Algoritmo implementado tendo como base o pseudocodigo apresentado no
 * livro "Redes Neurais Artificiais para engenharia e ciencias aplicadas"
 * do autor Ivan Nunes da Silva.
 * 
 * Capitulo 4.3.
 * 
 * @author Augusto Branquinho
 */
public class AdalineOperation {

	public static void main(String[] args) {
		double[] pesos = { 0.01222577719907951, 0.004762759645191947, -0.009727417287218335, 0.0020898259147021994 };

		double[][] amostras = new double[][] {
				{-1.0, -1.0, -1.0, -1.0 },
				{ 0.1,  0.3,  0.6,  0.5 },
				{ 0.4,  0.7,  0.9,  0.7 },
				{ 0.7,  0.2,  0.8,  0.1 }};

		double[] saidas = new double[] { 1.0, -1.0, -1.0, 1.0 };

		double eqmMedio = Eqm.calculateEQM(amostras, saidas, pesos);

		System.out.println("EQM medio " + eqmMedio);
	}

}

Abraços pessoal, até um próximo tema.

Redes Neurais Artificiais (Perceptron) - Parte 02

17. maio 2013 10:50 by BBranquinho in Java, Redes Neurais Artificiais  //  Tags: , ,   //   Comentários (0)

Aew meus amigos.

Hoje vou apresentar para vocês a rede neural Perceptron. Este rede e a mais simples e mostra uma base para redes neurais mais complexas.

O vídeo a seguir apresenta está rede neural.

O algoritmo abaixo foi implementado usando o programa Wolfram Mathematica e apresenta o treinamento da rede Perceptron.

(* Algoritmo Perceptron *)
(* 1. Conjunto de amostras de treinamento *)
x = {{-1.0, -1.0, -1.0, -1.0},
   {0.1, 0.3, 0.6, 0.5},
   {0.4, 0.7, 0.9, 0.7},
   {0.7, 0.2, 0.8, 0.1}};

(* 2. Saídas para o conjunto de entrada *)
d = {1, -1, -1, 1};

(* 3. Recupera a quantidade de amostras *)
quantidadeAmostras = Dimensions[x][[2]];

(* 4. Pesos gerados aleatoriamente entre 0 e 1 para cada amostra de \
treinamento *)
w = RandomReal[1, quantidadeAmostras];

(* 5. Taxa de aprneizado *)
taxaAprendizado = 0.5;

(* 6. Contador de épocas *)
epoca = 0;

(* 7. Função degrau que representa a função de saída *)
sinal[u_] := If [u >= 0.0, 1, -1];

(* 8. é realizado o treinamento dos pesos *)
erro = "existe";

While[erro == "existe",
  {
   erro = "inexiste";
   epoca++;
   
    Do[
    {
     u = Transpose[x][[i]]*w;
     y = sinal[Total[u]];
     If[y != d[[i]],
      {
       erro = "existe";
       w = w + taxaAprendizado * (d[[i]] - y) * Transpose[x][[i]];
       }]
     }, {i, quantidadeAmostras}];
   }];

Print["Quantidade de épocas é ",  epoca];
Print["Pesos da rede são ", w];
Plot3D[{-w[[1]]/w[[4]] - (w[[2]]/w[[4]]) x - (w[[3]]/w[[4]]) y}, {x, 
  0, 1}, {y, -1, 1}, PlotRange -> {0.0, 1.0}, ClippingStyle -> None]
(* Pontos para serem plotados *)
data1 = {{0.1, 0.4, 0.7}, {0.5, 0.7, 0.1}};
data2 = {{0.6, 0.9, 0.8}, {0.3, 0.7, 0.2}};
dataPlot = {data1, data2};
ListPointPlot3D[dataPlot, PlotStyle -> {PointSize [Large]}]

(* End of internal cache information *)

O código a seguir apresenta a implementação do algoritmo de treinamento da rede Perceptron.

package org.wpattern.redes.neurais.artificiais.capitulo3;

import java.util.Random;

/**
 * Algoritmo implementado tendo como base o pseudocodigo apresentado no
 * livro "Redes Neurais Artificiais para engenharia e ciencias aplicadas"
 * do autor Ivan Nunes da Silva.
 * 
 * Capitulo 3.4.
 * 
 * @author Augusto Branquinho
 */
public class PerceptronTraining {

	public static void main(String[] args) {
		Random random = new Random(System.currentTimeMillis());

		// 1. Criando o conjunto de amostra de testes. x^(k)
		double[][] amostras = new double[][] {
				{-1.0, -1.0, -1.0, -1.0 },
				{ 0.1,  0.3,  0.6,  0.5 },
				{ 0.4,  0.7,  0.9,  0.7 },
				{ 0.7,  0.2,  0.8,  0.1 }};

		// 2. Saida desejada para cada amostra. d^(k)
		double[] saidas = new double[] { 1.0, -1.0, -1.0, 1.0 };

		// 3. Realizar o sorteio dos pesos aleatoriamente.
		double[] pesos = new double[saidas.length];

		for (int i = 0; i < pesos.length; i++) {
			pesos[i] = 1.0 / (random.nextInt(100) + 1.0);
			System.out.println(String.format("Peso inicial %s = %s", i, pesos[i]));
		}

		// 4. Especificando a taxa de aprendizagem.
		double taxaAprendizado = 0.05;

		// 5. Iniciando o contador de epocas.
		int epoca = 0;

		// 6. Repetir as instrucoes enquanto existir erro.
		String erro;

		do {
			// 6.1. Nao existe erro.
			erro = "inexiste";

			// 6.2. Para todas as amostras de treinamento {x^(k), d^(k)}.
			for (int k = 0; k < amostras.length; k++) {
				// 6.2.1. Multiplicar o peso por uma dada amostra.
				// Pode ser usado um vetor para guardar os resultados.
				// Contudo, achei mais facil ja fazer a soma diretamente.
				double u = 0.0;

				// A inversao das variaveis i e k corresponde a transposta da matriz.
				for (int i = 0; i < pesos.length; i++) {
					u += pesos[i] * amostras[i][k];
				}

				// 6.2.2. Verificar o sinal de saida.
				int y = sinal(u);

				// 6.2.3. Verificando o sinal treinado e o valor desejado da amostra.
				if (y != saidas[k]) {
					// 6.2.3.1. é realizado o ajuste de pesos e marcamos que existe erro.
					double aprendizado = taxaAprendizado * (saidas[k] - y);
					for (int i = 0; i < pesos.length; i++) {
						pesos[i] = pesos[i] + aprendizado * amostras[i][k];
					}

					erro = "existe";
				}
			}

			// 6.3. Incremento da epoca.
			epoca++;
		} while (erro.equals("existe"));

		String formatoVetor = "{ ";
		System.out.println();
		System.out.println("Numero de epocas " + epoca);
		for (int i = 0; i < pesos.length; i++) {
			System.out.println(String.format("Peso final %s = %s", i, pesos[i]));
			formatoVetor += pesos[i] + (((i + 1) != pesos.length) ? ", " : "");
		}
		formatoVetor += " }";
		System.out.println(formatoVetor);
	}

	private static int sinal(double u) {
		return (u >= 0.0) ? 1 : -1;
	}

}

Para realizar a fase de operação quando já temos uma rede trienada temos o seguinte algoritmo:

package org.wpattern.redes.neurais.artificiais.capitulo3;

/**
 * Algoritmo implementado tendo como base o pseudocodigo apresentado no
 * livro "Redes Neurais Artificiais para engenharia e ciencias aplicadas"
 * do autor Ivan Nunes da Silva.
 * 
 * Capitulo 3.4.
 * 
 * @author Augusto Branquinho
 */
public class PerceptronOperation {

	public static void main(String[] args) {
		// 1. Amostra a ser classificada (Exemplo) (x).
		//double[] amostra = new double[] { -1.0, 0.1, 0.4, 0.7 }; // Classe A (1).
		//double[] amostra = new double[] { -1.0, 0.3, 0.7, 0.2 }; // Classe B (-1).
		//double[] amostra = new double[] { -1.0, 0.6, 0.9, 0.8 }; // Classe B (-1).
		double[] amostra = new double[] { -1.0, 0.5, 0.7, 0.1 }; // Classe A (1).

		// 2. Valores ajustados de pesos encontrados no treinamento (Exemplo) (w).
		double[] pesos = new double[] {-1.89043,6.29312,-7.26876,0.68572};

		// 3. Executar as seguintes instrucoes.
		// 3.1. Multiplicar os pesos pela amostra e resultar com a soma (u).
		double u = 0.0;
		for (int k = 0; k < amostra.length; k++) {
			u += pesos[k] * amostra[k];
		}

		// 3.2. Verificar o sinal.
		int y = sinal(u);

		// 3.3. Verificando a classe da amostra.
		if (y == -1) {
			System.out.println("Amostra da classe A (-1).");
		} else if (y == 1) {
			System.out.println("Amostra da classe B (1).");
		}
	}

	private static int sinal(double u) {
		return (u >= 0.0) ? 1 : -1;
	}

}

Até o próximo post sobre a rede Adaline, abraços.

Redes Neurais Artificiais (Introdução) - Parte 01

15. maio 2013 23:18 by BBranquinho in Java, Redes Neurais Artificiais  //  Tags: , ,   //   Comentários (0)

Aew meus amigos, tudo bem?

Hoje vou apresentar para vocês um tema muito interessante da área de Inteligência Artificial conhecida como Redes Neurais Artificiais. Em específico irei tratar das redes Perceptron e Adaline.

Livro Redes Neurais Artificiais para engenharia e ciências aplicadas. Autor: Ivan Nunes da Silva.

Para o estudo deste tema sugiro o livro SILVA, I. N.; Redes Neurais Artificiais para engenharia e ciências aplicadas. Mais informações: http://laips.sel.eesc.usp.br/. Ele apresenta uma introdução ao tema de forma bem concisa e simples.

Os materiais deste post e as referências pode ser encontrado em:

Skydrive: http://sdrv.ms/15N1DGY 

SVN: https://wpattern.codeplex.com/ (SOURCE CODE => examples => java => wpattern-redes-neurais-artificiais)

O livro "Simon O. Haykin. Neural Networks and Learning Machines (3rd Edition). 2008." possui um material mais avançado e é uma excelente opção para aprofundar neste tema.

Abaixo está a apresentação que irei usar neste trabalho. 

 
Inicialmente mostro uma introdução sobre redes neurais no vídeo abaixo.
 
 
 
Abraços pessoal, até a continuação deste tema.

Introdução ao JavaFF GUI

3. maio 2013 00:21 by BBranquinho in Java, Planejador, Planner  //  Tags:   //   Comentários (0)

Aew amigos nerds.

Vou hoje complementar um trabalho que estive desenvolvendo. Novamente irei falar sobre o JavaFF e demonstrar como usar ele em um projeto que envolva busca e/ou planejamento.

Antes de começar se vocês gostarem do trabalho que desenvolva sigam meu canal do youtube, deem joinha nos vídeos e curtam a página do blog no facebook.

Abaixo estão alguns artigos do grupo de IA da UFU da área de planejamento. Não irei tratar deles mas podem ser usados como referência para trabalhos futuros. Além de acessar pelo Scribd estes artigos também podem ser baixados no skydrive em Generating plans using LRTA* e Solving Planning Problems with LRTA*.

2013 05 03 Generating Plans Using LRTA BRACIS by Augusto Afonso Borges Branquinho

2013 05 03 Solving Planning Problems With LRTA ICEIS by Augusto Afonso Borges Branquinho

No vídeo abaixo explico um pouco sobre algoritmos de busca em tempo real e planejamento usando o planejador JavaFF. É apenas uma breve explicação já que não entrei em detalhes pois seria preciso de muito tempo para isso rsrs Mas acredito que seja uma base para iniciar os estudos sobre estes temas.

Infelizmente não foi possível neste momento gravar o vídeo do uso do ambiente de testes do JavaFF e da implementação de um algoritmo. Assim que possível irei fazer o vídeo e posto para vocês. Mas para atender essa fase inicial vou descrever o passo a passo de como usar o projeto de exemplo e alguns detalhes do exemplo do código de busca.

  1. Realizar o download do arquivo "javaff_example.zip" disponível em: https://code.google.com/p/javaffgui/downloads/list
  2. Descompactar o arquivo "javaff_example.zip".
  3. Para criar os algoritmos e usar o ambiente de testes eu indico o uso da IDE Eclipse. Ela está disponível em http://www.eclipse.org/downloads/
  4. Após o download do eclipse é necessário apenas descompactar e executar "eclipse.exe".
  5. Após a IDE estar aberta é preciso importar o projeto. Para isso vamos no menu "File" => "Import ..." => "Existing Projects into Workspace" => "Next". Na próxima parte é preciso colocar em "Select root directory" o caminho em que o projeto de exemplo foi descompactado. Em seguida pressionamos "Finish" e o projeto já estará disponível.
  6. Dentro do projeto "javaff_example" temos a pasta "problems" que possui o conjunto de domínios e problemas. Na pasta "src" estão os códigos de nosso projeto.
  7. Abaixo mostro o código de exemplo do algoritmo de busca e sua classe principal. Para executar o projeto é preciso apenas executar a classe "Main" que o ambiente de testes do JavaFF é exibido.
  8. Os códigos abaixo estão comentados com os principais detalhes necessário para realizar a implementação de um algoritmo de busca dentro do ambiente do JavaFF.

Classe "Main.java" responsável por iniciar a aplicação.

package org.wpattern.algoritmos;

import java.util.ArrayList;
import java.util.List;

import org.wpattern.javaff.gui.JavaFFGui;

public class Main {

	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		JavaFFGui javaff = new JavaFFGui();

		// Folders with domains and problem of planning.
		List<String> paths = new ArrayList<String>();
		paths.add("problems");

		// Start the environment loading the algorithm "AlgorithmSearch.class".
		// To load more algorithms we must add each algorithm,
		// for example: javaff.startApplication(paths, AlgorithmSearch.class, HillClimbing.class);
		javaff.startApplication(paths, AlgorithmSearch.class);
	}

}

A seguir na classe "AlgorithmSearch.java" temos um exemplo de algoritmo de busca.

package org.wpattern.algoritmos;

import java.util.Hashtable;
import java.util.LinkedList;

import javaff.annotation.AlgorithmParameter;
import javaff.planning.State;
import javaff.search.data.Search;

import org.apache.log4j.Logger;

// All search algorithms must extend the class "Search" and implements the methods "Search".
public class AlgorithmSearch extends Search {

	private Logger logger = Logger.getLogger(this.getClass());

	// Annotation @AlgorithmParameter is used to inject parameters from test environment (JavaFF GUI).
	// Is allowed use this annotation just in primitive types (long, double, int, ...)
	@AlgorithmParameter
	private Long parameter;

	private LinkedList<State> open;

	private Hashtable<Integer, State> closed;

	public AlgorithmSearch(State s) {
		super(s);
		this.open = new LinkedList<State>();
		this.closed = new Hashtable<Integer, State>();
	}

	@SuppressWarnings("unchecked")
	public void updateOpen(State S) {
		// Method "getNextStates" return all successors to a specific state.
		this.open.addAll(S.getNextStates(this.filter.getActions(S)));
	}

	public boolean needToVisit(State s) {
		Integer Shash = new Integer(s.hashCode());
		State D = this.closed.get(Shash);

		if (this.closed.containsKey(Shash) && D.equals(s)) {
			return false;
		}

		this.closed.put(Shash, s);

		return true;
	}

	// The search will start in this method.
	@Override
	public State search() {
		// Log about the search. We can use 6 types of log: Fatal, Error, Warn, Info, Debug, Trace.
		if (this.logger.isDebugEnabled()) {
			this.logger.debug("Parameter " + this.parameter);
		}

		this.open.add(this.start);

		// When the variable "stopSearch" is true we must stop the search.
		// That is required because the time limit was reached.
		while (!this.open.isEmpty() && !this.stopSearch) {
			State s = this.open.removeFirst();

			if (this.needToVisit(s)) {
				this.nodeCount++;

				if (s.goalReached()) {
					// Solution founded.
					return s;
				} else {
					this.updateOpen(s);
				}
			}
		}

		// Search failed.
		return null;
	}
}

Após executar o projeto pela classe "Main.java" temos a seguinte interface como é mostrada na figura a seguir.

Ambiente de testes do JavaFF.

Neste ambiente temos as seguintes opções:

  1. Selecionar os domínios e os respectivos problemas em que será executado a busca e o planejamento.
  2. Selecionar os algoritmos de busca e preencher os seus parâmetros. Este algoritmos serão executados em cada um dos problemas selecionados.
  3. Monitorar o log e alterar sua prioridade (Fatal, Error, Warn, Info, Debug, Trace).
  4. Determinar o limite de tempo para cada execução de um algoritmo.
  5. Determinar o número de execuções de cada algoritmo.

Espero que tenham gostado do post pois irei fazer mais trabalhos na área de IA. Em breve pretendo tratar de temas mais interessantes ainda, sendo que ele será sobre técnicas de Reconhecimento de Padrões. Assim que tiver o vídeo do uso do ambiente eu postarei para vocês.

Até mais meus amigos.

Introdução ao Spring Data JPA (Criação e Desenvolvimento do Projeto) - Parte 02

25. novembro 2012 11:34 by BBranquinho in Java, Spring  //  Tags: ,   //   Comentários (9)

Olá pessoal.

O projeto pode ser acessado e baixado em http://wpattern.codeplex.com no caminho "source code => examples => java => wpattern-frameworks-all".

Continuando o trabalho com o Spring Data JPA irei falar da implementação da entidade e do repositório. A primeira coisa que precisamos fazer é adicionar as dependências do maven ao projeto, como é mostrado a seguir.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<artifactId>wpattern-frameworks-all</artifactId>
		<groupId>br.com.wpattern.frameworks</groupId>
		<version>0.0.1-SNAPSHOT</version>
		<relativePath>..</relativePath>
	</parent>
	<artifactId>wpattern-frameworks-spring-data</artifactId>

	<dependencies>
		<!-- JAVAX INJECT -->
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
		</dependency>

		<!-- COMMONS LANG3 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
		</dependency>

		<!-- SPRING TEST -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
		</dependency>
		
		<!-- SPRING CONTEXT -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
		</dependency>

		<!-- SPRING DATA JPA -->
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-jpa</artifactId>
		</dependency>

		<!-- SLF4J -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
		</dependency>

		<!-- MySQL DRIVER -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>

		<!-- HIBERNATE ENTITYMANAGER -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
		</dependency>
	</dependencies>
</project>

Temos a classe BaseEntities que é usado como sendo a base de todas as entidades. O mais importante desta classe é a herança da AbstractPersistable, onde passamos o tipo PK que corresponde a tipagem da chave primária de uma entidade.

package br.com.wpattern.frameworks.spring.data.utils;

import java.io.Serializable;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.springframework.data.jpa.domain.AbstractPersistable;

/**
 * Base of all entities.
 * 
 * @author Branquinho
 */
public abstract class BaseEntities<PK extends Serializable> extends AbstractPersistable<PK> implements Serializable {

	private static final long serialVersionUID = 201210190226L;

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
	}

	@Override
	public boolean equals(Object obj) {
		return EqualsBuilder.reflectionEquals(this, obj);
	}

}

Como temos apenas uma tabela teremos apenas uma entidade. Esta entidade possui o nome de UserEntity que é responsável por mapear o código com a entidade/tabela TB_USER do banco. O mapeamento JPA é o mesmo que usamos em outros projetos, sendo assim, não irei entrar em detalhes das anotações no texto apesar de falar mais sobre elas no vídeo ao final do post.

package br.com.wpattern.frameworks.spring.data.entities;

import java.util.Date;

import javax.persistence.AttributeOverride;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import br.com.wpattern.frameworks.spring.data.utils.BaseEntities;

@Entity
@Table(name = "TB_USER")
@AttributeOverride(name = "id", column = @Column(name = "PK_ID"))
public class UserEntity extends BaseEntities<Long> {

	private static final long serialVersionUID = 201210190327L;

	@Column(name="LOGIN", length=30, nullable=false, unique=true)
	private String login;

	@Column(name="PASSWORD", length=127, nullable=false, unique=false)
	private String password;

	@Column(name="REGISTER_DATE", nullable=false, unique=false)
	@Temporal(value=TemporalType.TIMESTAMP)
	private Date registerDate;

	@Column(name="AGE", nullable=false, unique=false)
	private Integer age;

	public UserEntity() {
	}

	public UserEntity(String login, String passwd, Date registerDate, Integer age) {
		super();
		this.login = login;
		this.password = passwd;
		this.registerDate = registerDate;
		this.age = age;
	}

	@Override
	public void setId(Long id) {
		super.setId(id);
	}

	public String getLogin() {
		return this.login;
	}

	public void setLogin(String login) {
		this.login = login;
	}

	public String getPassword() {
		return this.password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public Date getRegisterDate() {
		return this.registerDate;
	}

	public void setRegisterDate(Date registerDate) {
		this.registerDate = registerDate;
	}

	public Integer getAge() {
		return this.age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

}

Para cada entidade teremos um repositório, sendo assim, temos o repositório UserRepository mostrado abaixo. Ao herdar a interface JpaRepository temos todas as operações básicas do CRUD e mais algumas operações. Na interface JpaRepository precisamos definir a entidade e a chave primária da entidade.

package br.com.wpattern.frameworks.spring.data.entities;

import java.util.Date;

import javax.persistence.AttributeOverride;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import br.com.wpattern.frameworks.spring.data.utils.BaseEntities;

@Entity
@Table(name = "TB_USER")
@AttributeOverride(name = "id", column = @Column(name = "PK_ID"))
public class UserEntity extends BaseEntities<Long> {

	private static final long serialVersionUID = 201210190327L;

	@Column(name="LOGIN", length=30, nullable=false, unique=true)
	private String login;

	@Column(name="PASSWORD", length=127, nullable=false, unique=false)
	private String password;

	@Column(name="REGISTER_DATE", nullable=false, unique=false)
	@Temporal(value=TemporalType.TIMESTAMP)
	private Date registerDate;

	@Column(name="AGE", nullable=false, unique=false)
	private Integer age;

	public UserEntity() {
	}

	public UserEntity(String login, String passwd, Date registerDate, Integer age) {
		super();
		this.login = login;
		this.password = passwd;
		this.registerDate = registerDate;
		this.age = age;
	}

	@Override
	public void setId(Long id) {
		super.setId(id);
	}

	public String getLogin() {
		return this.login;
	}

	public void setLogin(String login) {
		this.login = login;
	}

	public String getPassword() {
		return this.password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public Date getRegisterDate() {
		return this.registerDate;
	}

	public void setRegisterDate(Date registerDate) {
		this.registerDate = registerDate;
	}

	public Integer getAge() {
		return this.age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

}

Apenas com isso e mais algumas configurações do Spring já temos o acesso ao banco de dados e todas as operações do CRUD. Abaixo estão alguns testes unitários do repositório.

package br.com.wpattern.frameworks.test.spring.data;

import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/ctx-wpattern-frameworks-spring-data.xml" })
public abstract class AbstractSpringDataTest {

}
package br.com.wpattern.frameworks.test.spring.data.repositories;

import java.util.Date;
import java.util.List;

import javax.inject.Inject;

import org.apache.log4j.Logger;
import org.junit.Test;

import br.com.wpattern.frameworks.spring.data.entities.UserEntity;
import br.com.wpattern.frameworks.spring.data.repositories.IUserRepository;
import br.com.wpattern.frameworks.test.spring.data.AbstractSpringDataTest;

public class UserRepositoryTest extends AbstractSpringDataTest {

	private Logger logger = Logger.getLogger(this.getClass());

	@Inject
	private IUserRepository userRepository;

	@Test
	public void testList() {
		List<UserEntity> users = this.userRepository.findAll();

		this.logger.debug(users);
	}

	@Test
	public void testInsert() {
		UserEntity user = new UserEntity();

		user.setLogin("LOGIN_" + System.currentTimeMillis());
		user.setPassword("PASSWORD");
		user.setRegisterDate(new Date());
		user.setAge(22);

		this.logger.debug(this.userRepository.save(user));
	}

	@Test
	public void testFindByLogin() {
		UserEntity user = this.userRepository.findByLogin("login2");

		this.logger.debug(user);
	}

}

O vídeo abaixo mostra os detalhes desta implementação.

Abraços e até o próximo post.

WPattern

O objetivo deste blog é de disponibilizar os resultados dos meus estudos. Não será tratada apenas uma tecnologia ou área, mas qualquer tópico que seja interessante e possa contribuir com a comunidade de desenvolvedores, comunidade científica e meus alunos. Entretanto, meus trabalhos sempre estão voltado principalmente para as tecnologias .NET, Java e C/C++.

Posts Recentes

Google Translator

JetBrains

JetBrains: Ferramentas de desenvolvimento com .NET.

ReSharper: Excelente ferramenta para .NET.