Esse artigo é continuação do
TUTORIAL JAVA + FLEX NA PRÁTICA 1/6
TUTORIAL JAVA + FLEX NA PRÁTICA 2/6
TUTORIAL JAVA + FLEX NA PRÁTICA 3/6
TUTORIAL JAVA + FLEX NA PRÁTICA 4/6
TUTORIAL JAVA + FLEX NA PRÁTICA 5/6
TUTORIAL JAVA + FLEX NA PRÁTICA 6/6
Não definitivamente você não está delirando e nem eu esqueci conceitos simples da matemática, realmente criei mais um tutorial, a 7/6, o que estou considerando Bônus, para fazer algumas modificações e implementar algumas funcionalidades.
Antes gostaria de agradecer pela participação do pessoal, muitos entenderam o objetivo do tutorial e com certeza fizeram bom proveito, fiquei sabendo este mês de julho que alguns mudaram a forma de trabalhar com Java + flex através deste tutorial
. Através do mesmo recebi ótimos contatos e oportunidades profissionais, porém, como sempre há alguém que quer mais e gostaria de mais um empurram, então vamos direto ao assunto que tempo é dinheiro.
Essa parte vamos tratar mais de relacionamentos entre tabelas, como tratar esses relacionamentos no Flex e como mostrar mais de um objeto no datagrid... vamos a prática.
Implementação no Java
Assim como fizemos na nossa classe Estado vamos criar nossa Classe Cidade, classe essa que fará o relacionamento mais comum e a dúvida mais comum depois que você começa a programar, vamos ao código:
Cidade.java
-
@Table(name="cidade")
-
public class Cidade {
-
-
@Id @GeneratedValue(strategy = GenerationType.AUTO)
-
private long idCidade;
-
-
@ManyToOne(fetch = FetchType.EAGER)
-
@JoinColumn(name="codEstado",insertable=true,updatable=true)
-
@Fetch(FetchMode.JOIN)
-
@Cascade(CascadeType.SAVE_UPDATE)
-
private Estado estado;
-
-
private String nome;
-
-
private String sigla;
-
-
return sigla;
-
}
-
-
this.sigla = sigla;
-
}
-
-
public long getIdCidade() {
-
return idCidade;
-
}
-
-
public void setIdCidade(long idCidade) {
-
this.idCidade = idCidade;
-
}
-
-
public Estado getEstado() {
-
return estado;
-
}
-
-
public void setEstado(Estado estado) {
-
this.estado = estado;
-
}
-
-
return nome;
-
}
-
-
this.nome = nome;
-
}
-
-
}
Vale comentar algumas anotações que usei aqui:
@ManyToOne(fetch = FetchType.EAGER) -> como o relacionamento é de “N para 1”, uma Cidade pertence a um Estado e o Estado pode ter várias Cidade, usamos a anotação @ManyToOne e também usamos o FethType:
EAGER -> Sempre que o Objeto pai for trazido o atributo mapeado também será trazido) cuidado ao usar pois se for relacionamentos mais complexo, ou melhor, que contém muitos objetos dentro do outro pode ficar muito lento, no nosso exemplo não temos que ser preocupar com isso.
LAZY -> Sempre que o objeto pai for trazido o atributo mapeado só será trazido quando acessado pela primeira vez(muito usado quando é List, Collection para evitar o que citei logo acima).
@JoinColumn(name="codEstado",insertable=true,updatable=true) -> informamos qual é o campo é a chave estrangeira, no caso da Cidade a chave estrangeira é o codEstado. O insertable e o updatable quando indicados como true significa que esse objeto tem que ser inserido ou atualizado quando o objeto pai é inserido ou atualizado, resumindo, Toda vez que for inserir e atualizar um Cidade também será inserido ou atualizado um Estado.
@Fetch(FetchMode.JOIN) -> informamos que estamos juntando as duas tabelas, melhor dizendo, como se estivesse usando o Inner Join na injeção de SQL.
@Cascade(CascadeType.SAVE_UPDATE)-> por ultimo a permissão que esse atributo pode interferir na Classe ao qual está fazendo o relaciomento. Explico, ao colocar SAVE_UPDATE se caso você esteja inserindo uma cidade e o estado ainda não foi inserido, ele automaticamente vai adicionar esse Estado, pegar o id do mesmo e gravar na tabela cidade no campo codEstado, Hibernate é Kara
.
Depois de explicado as anotações as outras classes que ficam no Java já foram explicadas e só serão adicionadas logo abaixo:
CidadeRepository.java
CidadeService.java
-
@Service(value="CidadeService")
-
public class CidadeService {
-
-
CidadeRepository cidadeRepository;
-
-
@Autowired
-
public void setCidadeRepository(CidadeRepository cidadeRepository) {
-
this.cidadeRepository = cidadeRepository;
-
}
-
-
public void save(Cidade cidade){
-
cidadeRepository.save(cidade);
-
}
-
-
public void remove(Cidade cidade){
-
cidadeRepository.remove(cidade);
-
}
-
-
public ListfindAll(){
-
return cidadeRepository.findAll();
-
}
-
-
return cidadeRepository.findByName(nome);
-
}
-
-
}
CidadeDao.java
-
public class CidadeDao extends HibernateDaoSupport
-
implements CidadeRepository {
-
-
@Autowired
-
public CidadeDao(@Qualifier("sessionFactory") SessionFactory sessionFactory) {
-
// TODO Auto-generated constructor stub
-
super.setSessionFactory(sessionFactory);
-
}
-
-
@Override
-
public void remove(Cidade cidade) {
-
// TODO Auto-generated method stub
-
getHibernateTemplate().delete(cidade);
-
}
-
-
@SuppressWarnings("unchecked")
-
@Override
-
// TODO Auto-generated method stub
-
return getHibernateTemplate().loadAll(Cidade.class);
-
}
-
-
@SuppressWarnings("unchecked")
-
@Override
-
// TODO Auto-generated method stub
-
return getHibernateTemplate().find("from Cidade" +
-
" where nome like '%" + nome + "%'");
-
}
-
-
@Override
-
public void save(Cidade cidade) {
-
// TODO Auto-generated method stub
-
getHibernateTemplate().saveOrUpdate(cidade);
-
}
-
-
}
Agora é só adicionar o serviço no blazeds e ir para a parte flex.
remoting-config.xml
-
-
-
spring
-
<source />CidadeService
OBS. Aqui já começa uma pequena discussão, se você perceber os Repository, Service e Dao de Cidade e Estado são praticamente idênticos, e muitos vão optar por trabalhar com classes Genéricas, tipo RepositoryGeneric, DaoGeneric. Nada contra, só que eu prefiro deixar separado, se você usar genérico tome muito cuidado, uma vez tomei o genérico de novalgina e fiquei uma semana mal, acabou o genérico comprei novalgina e a dor de cabeça passou em 30 minutos, hehe.
Outra coisa aí sim eu recomendo é o seguinte, de vez de ter um Service para a cidade e outra para estado criar um tipo addresService, cuja esse serviço manipularia o estado, a cidade o bairro... enfim, tudo que tem haver com endereço, isso é normal, o service na verdade é isso, mais como nos exemplos fica tudo separado as pessoas colocam separado, então, mesmo não fazendo assim neste exemplo recomendo a todos depois fazer isso neste exemplo, considere dever de casa
.
Implementação no Flex
No flex a implementação é mais simples ainda, a base de ctrl+c ctrl+v, vamos ao código:
Cidade.as
-
[RemoteClass(alias="com.saberprogramar.business.entitys.Cidade")]
-
[Bindable]
-
public class Cidade
-
{
-
-
public var idCidade:Number;
-
-
public var estado:Estado;
-
-
public var nome:String;
-
-
public var sigla:String;
-
-
}
A única coisa que Vale lembrar aqui é que como no Java você usa o relacionamento com a classe Estado, no Action script tem que acontecer a mesma coisa, se não você não relaciona objetos, tipo, ao invés de colocar “estado:Estado” colocar “idEstado:Number” vc não está programando orientado a objeto, você na verdade está criando classes que sejam clone das suas tabelas do banco de dados, fazendo isso você está perdendo o melhor que o mundo OO pode te oferecer. É aqui que vejo uma constante dúvida que tenho recebido por contato aqui no Blog, então aí vai:
- Não! de maneira nenhuma deixe de fazer os relacionamentos dos seus objetos, uma cidade faz parte de um Estado e não de um código do estado, então... tanto no Java, como no Action Script, quanto no php e outra qualquer linguagem não considere seus objetos uma cópia de suas tabelas do banco de dados.
- Se no Java você tem um atributo “Estado estado” no actionScript você vai ter um ”estado:Estado”. Quando usamos RemoteObject o action script tem que ser igual ao Java ou ao php, é um clone, não pode ter um “Estado estado” no Java e um “idEstado:Number” no Action Script, não vai funcionar e você vai ter aquela sensação, é alguma bobeira que eu não estou vendo.
CidadeDelegate.as
-
public class CidadeDelegate extends AbstractDelegate
-
{
-
-
[Autowire(bean="cidadeService")]
-
public var cidadeService:RemoteObject;
-
-
public function CidadeDelegate()
-
{
-
super();
-
}
-
-
//AS OPERAÇÕES CRUD
-
public function findAll():AsyncToken{
-
return cidadeService.findAll();
-
}
-
-
public function findByName(nome:String):AsyncToken{
-
return cidadeService.findByName(nome);
-
}
-
-
public function save(cidade:Cidade):AsyncToken{
-
return cidadeService.save(cidade);
-
}
-
-
public function remove(cidade:Cidade):AsyncToken{
-
return cidadeService.remove(cidade);
-
}
-
-
}
CidadeEvent.as
-
public class CidadeEvent extends Event
-
{
-
-
public static const SAVE:String = "saveCidade";
-
public static const REMOVE:String = "removeCidade";
-
-
public function CidadeEvent(type:String)
-
{
-
super(type);
-
}
-
-
}
ICidadeController.as
-
public interface ICidadeController
-
{
-
-
function get cidadeList():ArrayCollection;
-
-
function findAll():void;
-
-
function findByName(nome:String):void;
-
-
function save(cidade:Cidade):void;
-
-
function remove(cidade:Cidade):void;
-
-
}
CidadeController.as
-
public class CidadeController extends AbstractController
-
implements ICidadeController{
-
-
[Bindable]
-
public var cidadeList:ArrayCollection;
-
-
[Autowire(bean="cidadeDelegate")]
-
public var cidadeDelegate:CidadeDelegate;
-
-
public function CidadeController()
-
{
-
super();
-
}
-
-
public function findAll():void{
-
executeServiceCall(cidadeDelegate.findAll(),onFindAll,onError);
-
}
-
-
public function findByName(nome:String):void{
-
executeServiceCall(cidadeDelegate.findByName(nome),onFindByName,onError);
-
}
-
-
public function save(cidade:Cidade):void{
-
executeServiceCall(cidadeDelegate.save(cidade),onSave,onError);
-
}
-
-
public function remove(cidade:Cidade):void{
-
executeServiceCall(cidadeDelegate.remove(cidade),onRemove,onError);
-
}
-
-
//*************** Handle Results ************************//
-
-
public function onFindAll(event:ResultEvent):void{
-
cidadeList = ArrayCollection(event.result);
-
}
-
-
public function onFindByName(event:ResultEvent):void{
-
cidadeList = event.result as ArrayCollection;
-
}
-
-
public function onSave(event:ResultEvent):void{
-
Swiz.dispatchEvent(new CidadeEvent(CidadeEvent.SAVE));
-
}
-
-
public function onRemove(event:ResultEvent):void{
-
Swiz.dispatchEvent(new CidadeEvent(CidadeEvent.REMOVE));
-
}
-
-
private function onError(event:FaultEvent):void{
-
Alert.show(event.fault.message,"ERROR");
-
}
-
-
}
Adicionados estas classes é só adicionar o mapeamento dos mesmos e o RemoteObjetct no nosso Beans.mxml.
-
<!-- cidade service -->
-
destination="CidadeService"
-
channelSet="{myAmfChannel}"/>
-
-
-
-
Agora vamos a interface(view) com algumas explicações:
CidadeView.mxml
-
<!--?xml version="1.0" encoding="utf-8"?-->
-
-
title="Cadastro de Cidades" fontSize="10" xmlns="flexmdi.containers.*"
-
xmlns:controls="com.flexpernambuco.controls.*"
-
creationComplete="{init()}" showCloseButton="true" close="{exit()}">
-
-
-
-
toolTip="Código Gerado Automático" text="{cidade.idCidade.toString()}"/>
-
-
labelField="nome" prompt="Selecione um Estado" tabIndex="1">
-
-
-
-
Agora vamos mostrar sua action:
CidadeAction.as
-
// ActionScript file
-
import com.saberprogramar.controllers.ICidadeController;
-
import com.saberprogramar.controllers.IEstadoController;
-
import com.saberprogramar.events.CidadeEvent;
-
import com.saberprogramar.models.entitys.Cidade;
-
import com.saberprogramar.models.entitys.Estado;
-
-
import mx.controls.dataGridClasses.DataGridColumn;
-
import mx.managers.PopUpManager;
-
-
import org.swizframework.Swiz;
-
-
[Bindable]
-
private var cidade:Cidade;
-
-
[Bindable]
-
[Autowire(bean="estadoController")]
-
public var controllerEstado:IEstadoController;
-
-
[Bindable]
-
[Autowire(bean="cidadeController")]
-
public var controller:ICidadeController;
-
-
private function init():void{
-
-
PopUpManager.centerPopUp(this);
-
-
Swiz.addEventListener(CidadeEvent.SAVE,onSaveComplete);
-
Swiz.addEventListener(CidadeEvent.REMOVE,onRemoveComplete);
-
-
findAll();
-
}
-
-
private function findAll():void{
-
controller.findAll();
-
controllerEstado.findAll();
-
}
-
-
private function save():void{
-
cidade = new Cidade();
-
stack.selectedChild = canvasForm;
-
}
-
-
private function update():void{
-
-
if (dgCidade.selectedItem != null){
-
-
dgCidade.setStyle("bordercolor",'black');
-
dgCidade.errorString = "";
-
-
cidade = dgCidade.selectedItem as Cidade;
-
stack.selectedChild = canvasForm;
-
-
}else {
-
dgCidade.setStyle("bordercolor",'red');
-
dgCidade.errorString = "Selecione uma Cidade para alterar";
-
}
-
-
}
-
-
private function remove():void{
-
-
if (dgCidade.selectedItem != null){
-
-
dgCidade.setStyle("bordercolor",'black');
-
dgCidade.errorString = "";
-
-
cidade = dgCidade.selectedItem as Cidade;
-
-
controller.remove(cidade);
-
-
}else {
-
dgCidade.setStyle("bordercolor",'red');
-
dgCidade.errorString = "Selecione uma Cidade para excluir";
-
}
-
-
}
-
-
private function confirm():void{
-
-
cidade.idCidade = new Number(txtIdCidade.text);
-
cidade.estado = cmbEstado.selectedItem as Estado;
-
cidade.nome = txtNome.text;
-
cidade.sigla = txtSigla.text;
-
-
controller.save(cidade);
-
-
}
-
-
private function cancel():void{
-
cidade = new Cidade();
-
stack.selectedChild = canvasDefault;
-
}
-
-
private function find():void{
-
-
if (txtFind.text != null){
-
controller.findByName(txtFind.text);
-
}
-
-
}
-
-
private function onSaveComplete(event:CidadeEvent):void{
-
stack.selectedChild = canvasDefault;
-
findAll();
-
}
-
-
private function onRemoveComplete(event:CidadeEvent):void{
-
stack.selectedChild = canvasDefault;
-
findAll();
-
}
-
-
private function colEstado(objCidade:Cidade, col:DataGridColumn):String{
-
return objCidade.estado.uf;
-
}
-
-
private function exit():void{
-
PopUpManager.removePopUp(this);
-
}
Como Pode perceber existe algumas novidades comparado ao código do estado, uma é a combo que carrega todos os estados:
-
labelField="nome" prompt="Selecione um Estado" tabIndex="1">
- O DataProvider da combo é o estadoList da nossa controllerEstado.
- o label Field é o “nome”(atributo da classe estado).
- prompt é o texto inicial da combo.
A parte mais interessante neste caso é o grid, usamos a função labelFunction:
Neste caso indicamos que o label desta coluna vem do retorno de uma função chamada colEstado:
-
private function colEstado(objCidade:Cidade, col:DataGridColumn):String{
-
return objCidade.estado.uf;
-
}
Se você perceber temos uma função que espera como retorno uma String, e aqui podemos ver já uma vantagem de usar os relacionamentos de objetos de maneira correta, uma cidade contém um estado, então ao fazer o que fizemos acima conseguimos pegar qualquer atributo da nossa classe Estado e mostrar no grid sem a necessidade de fazer um FindById ou algo parecido.
Bem, é isso, atualizei o código fonte, caso queiram podem baixar nos links logo abaixo, qualquer dúvida pode entrar em contato, ou se preferir postar um comentário.
Até a Próx.
Caso queira o projeto em java é só baixar aqui (sem as libs).
Caso queira o projeto em flex é só baixar aqui.




Pingback: TUTORIAL JAVA + FLEX NA PRÁTICA (8) - Datas | jandersonfc
Pingback: TUTORIAL JAVA + FLEX NA PRÁTICA (9) – Atualizando o Swiz | jandersonfc
Pingback: TUTORIAL JAVA + FLEX NA PRÁTICA (9) – Atualizando o Swiz - redeRIA | Agregador de noticias, artigos, tutoriais Flex, Flash, JavaFX, AJAX e Rich internet applications em geral!
Pingback: TUTORIAL JAVA + FLEX + IREPORT NA PRÁTICA (11) - redeRIA | Agregador de noticias, artigos, tutoriais Flex, Flash, JavaFX, AJAX e Rich internet applications em geral!