Galera estou começando com Flex e estou com o seguinte problema…
Tenho uma classe Venda que TEM-UM Regiao. Estou tentando trazer em um dataGrid/dataField o descritivo da Região (Ex.: Id_Venda: 1 - Regiao: Sudeste), mas não estou conseguindo a Regiao, esta retornando NULL.
Obs.: O Id retorno normalmente.
// *********** CLASSES JAVA **********
@Entity
@Table(name = "VENDA")
public class Venda {
@Id
@Column(name = "ID_VENDA")
private Integer id;
@ManyToOne
@JoinColumn(name = "ID_REGIAO")
private Regiao regiao;
//getters e setters
}
@Entity
@Table(name = "REGIAO")
public class Regiao {
@Id
@Column(name = "ID_REGIAO")
private Integer id;
@Column(name = "REG_DESC")
private String nome;
//getters e setters
}
public class VendaHibernate {
...
public Collection<Venda> obterVendas() {
Session session = ConnectionFactory.getConnectionHibernate();
String hql = "select venda from Venda as venda inner join venda.regiao as regiao";
Query query = session.createQuery(hql);
query.setMaxResults(10);
return query.list();
}
// *********** ACTION SCRIPT **********
package br.srv.work.flex.model
{
[RemoteClass(alias="br.srv.work.model.Venda")]
[Bindable]
public class Venda{
public var id:int;
public var quantidade:Number;
public var valor:Number;
public var regiao:Regiao;
}
}
package br.srv.work.flex.model
{
[RemoteClass(alias="br.srv.work.model.Regiao")]
[Bindable]
public class Regiao{
public var id:int;
public var nome:String;
}
}
// *********** VIEW - mxml**********
// Trecho do código do dataGrid
...
<mx:AdvancedDataGrid id="grdVenda" designViewDataType="tree" width="100%" height="100%" selectionMode="none" dataProvider="{vetorDadosVenda}">
<mx:columns>
<mx:AdvancedDataGridColumn headerText="Id" dataField="id"/> //AQUI O CONTEUDO É RETORNADO NORMALMENTE
<mx:AdvancedDataGridColumn headerText="Regiao" dataField="regiao.nome"/> //AQUI NÃO RETORNA NADA
</mx:AdvancedDataGrid>
Então, isto está acontecendo provavelmente por causa do lazy loading do hibernate. Quando você está do lado Java, o hibernate mantem o objeto “vivo” e quando você pede algum atributo dele que faz referência a alguma outra tabela, ele carrega esse objeto sob demanda.
Quando você serializa esse objeto mais externo via AMF, o Hibernate não tem tempo de carregar o objeto que compõe o outro objeto, pq afinal você não pediu isso (ao tentar acessar o atributo), sendo assim, vem null.
Infelizmente, o BlazeDS (acredito que você esteja utilizando ele) não suporta o lazy loading do Hibernate, sendo assim, você tem que trazer tudo de uma vez, ou seja, o objeto e todas as suas dependências. Apesar de não recomendado, você deve mudar a estratégia de carga do hibernate no relacionamento para EAGER.
Para fazer isso, nas anotações que correspondem aos relacionamentos entre as entidades, basta vc informar o fetch como EAGER:
@ManyToOne( fetch = FetchType.EAGER )
@JoinColumn(name = "ID_REGIAO")
private Regiao regiao;
Isso pode inpactar negativamente no desempenho do seu sistema e eu infelizmente não sei como contornar isso usando o BlazeDS. Não sei tbm se é possível contornar porque nunca fiz nenhum projeto “de verdade” usando o BlazeDS.
Testei e funfou com propriedade aninhada, dessa eu não sabia.
Achei que não seria o problema de lazy pq se fosse, ele receberia uma exceção em vez de apenas a propriedade região nula…[/quote]
Então, como eu falei, eu ainda não usei hibernate + blazeds pq não precisei, então eu agora que não sabia sobre a excessão. Mas me parece estranho disparar uma excessão pq vem um objeto apontanto para null. Tem certeza disso tbm? Depois vou testar.
Isso é certeza sim, é um problema bem conhecido e até tem tópico aqui no GUJ. Parece que o cara do StackOverFlow passou pelo mesmo problema do autor do tópico.
Dá uma olhada pra ver se ajuda.
[quote=renzonuccitelli] Isso é certeza sim, é um problema bem conhecido e até tem tópico aqui no GUJ. Parece que o cara do StackOverFlow passou pelo mesmo problema do autor do tópico.
Dá uma olhada pra ver se ajuda.
[]s[/quote]
Não sabia
Como nunca tinha feito, então não sabia. Obrigado pelo link
O que funcionou foi o DataGrid pegar a propriedade aninhada.
Vc chegou a debugar pra pelo menos descobrir onde é o Problema? debugue seu serviço remoto pra ver se ele está construindo o objeto de forma correta. Sendo a construção correta, debug o retorno da chamada remota pra descobrir se o BlazeDS está serializando direito.
@Entity
@Table(name = "VENDA")
public class Venda {
@Id
@Column(name = "ID_VENDA")
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
@ManyToOne
@JoinColumn(name = "ID_REGIAO")
private Regiao regiao;
//getters e setters
}
@Entity
@Table(name = "REGIAO")
public class Regiao {
@Id
@Column(name = "ID_REGIAO")
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
@Column(name = "REG_DESC")
private String nome;
//getters e setters
}
Não deu pra testar mais até aqui, acho que está tudo ok.
Agora no seu HQL.
public List<Venda> obterVendas() {
Session session = ConnectionFactory.getConnectionHibernate();
Query query = session.createQuery("select v from Venda v");
query.setMaxResults(10);
List<Venda> list = query.list(); //coloca um breakpoint e confere se o resultado está chegando aqui.
return list;
}
Para usar um objeto composto em um DataGrid, assunto que já está batido no forum.
<mx:DataGridColumn id="colunaRegiao"
labelFunction="labelFunctionRegiao" width="200"/>
private function labelFunctionRegiao(row:Object, column:DataGridColumn):String
{
var regiao:Regiao = row as Regiao;
return regiao.nome;
}