BISDAO Legacy: mudanças entre as edições

De BIS Wiki
Ir para navegação Ir para pesquisar
m Rodrigogml moveu a página Persistência para BISDAO sem deixar um redirecionamento
m Rodrigogml moveu a página BISDAO para BISDAO Legacy sem deixar um redirecionamento: Nova página do BISDAO criado para a v10
 
(6 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 1: Linha 1:
O BISCore oferece uma estrutura de persistência combinada com os recursos da JPA para simplificar a camada de persistência dos módulos. Essa estrutura prevê métodos para insert, update, delete e "find".
O BISKernel oferece uma estrutura de persistência combinada com os recursos da JPA para simplificar, ou mesmo evitar, a camada de persistência dos módulos. Essa estrutura prevê métodos para insert, update, delete e "find".
 
Seu funcionamento compreende os seguintes itens:
* '''[[BISVO]]''' - Um herdeiro de BISVO que represente a entidade principal a ser persistida. O objeto a ser manipulado no banco de dados.
* '''[[BISMO]]''' - MatchObject para os métodos de ''find''. O MatchObject representa um objeto de filtro para a busca no banco de dados.
* '''[[BISOrderBy]]''' - Objeto usado nos métodos de find que retornam mais de 1 item para descrever a ordem dos objetos.
* '''[[BISVO_]]''' - O MetaObject deve ser utilizado para indicar os ''atributos'' que queremos que o método de find busque automaticamente para popular cada objeto. Normalmente os métodos de ''find'' já trazem o atributos do VO populado, mas não os atributos das entidades relacionadas (relacionamento marcados como '''Lazy''' no JPA). Quando o carregamento deste objeto for desejado o herdeiro do [[BISVO_]] correspondente ao herdeiro do [[BISVO]] passado no construtor do BISDAO deve ser utilizado para indicar o caminho das propriedades que obrigatoriamente devem ser populadas. Em geral, se uma propriedade de um VO é solicitada todas as outras propriedades do mesmo VO que estão na mesma tabela serão poluladas automaticamente.


Para utilizar esta estrutura há algumas condições:
# O objeto a ser persistido deve estender BISDefaultVO.
# Para cada objeto a ser persistido, deve haver um MO correspondente, mesmo que sem qualquer atributo (classe vazia).
# A classe de persistência deve estender BISDefaultEJB3DAO. Esta classe utiliza 'generics', e recebe como parâmetro as classes de VO e MO do objeto a ser persistido.
# Deve ser Implementada uma interface deste DAO que por sua vez deve estender BISDefaultDAO.
# Implementar o método no Factory do Plugin para retornar o objeto  que implementa a interface do DAO.


{{nota|Padrão de Nomes|Para simplificação da programação em equipe e manutenção posterior lembre-se do padrão de nome dos objetos e classes adotados no BIS descritos no tópico [[Formatação_e_Escrita_de_Código#Conven.C3.A7.C3.B5es_de_Nome_do_BIS|Convenção de Nome do BIS]].}}
{{nota|Padrão de Nomes|Para simplificação da programação em equipe e manutenção posterior lembre-se do padrão de nome dos objetos e classes adotados no BIS descritos no tópico [[Formatação_e_Escrita_de_Código#Conven.C3.A7.C3.B5es_de_Nome_do_BIS|Convenção de Nome do BIS]].}}


Para exemplificar, imaginemos que o objeto em questão seja um "contato". Obviamente devemos ter o VO que o representa, se o objeto for batizado como "Contact" o nome do VO será ContactVO. Assim, para implementar a camada de persistência deste objeto devemos criar as seguintes classes e intarface:


* '''ContactMO:''' é o [[MatchObject]] utilizado nos métodos de busca automatizados do objeto. Este Objeto não precisa ter nenhum método, atributo ou construtor no seu interior a princípio. Seus atributos e métodos só precisam ser criados posteriormente de acordo com a necessidade de se realizar buscas do objeto.
{{nota|Extensão da BISDAO|Normalmente não é necessário estender BISDAO em outra classe. Bastando a instância-la e passando a classe adequada em seu construtor os métodos padrões do BISDAO já se tornam acessíveis.
{{java|ContactMO|<syntaxhighlight lang="java5">
 
public class ContactMO extends BISDefaultMO {
Ainda assim, é possível estender BISDAO em uma classe específica para a criação de métodos mais específicos que interagem diretamente com o JPA. Em geral estes métodos só serão necessários para ganhos de performance para métodos de consulta ou atualização do banco de dados.}}
}
 
</syntaxhighlight>}}
 
== Tratamento do Relacionamentos das Entidades ==
 
Este tópico relaciona o comportamento do BISDAO com às entidades relacionadas à entidade principal. Mas lembre-se que não cabe ao BISDAO realizar validações, o objeto que chega aqui deve estar pronto para ser persistido, para validar consulte o [[BISValidator]].
 
O BISDAO se orienta pelas annotations do JPA e do [[BISMeta Annotations]], logo seu correto funcionamento depende da informação correta informada nessas annotations. Veja a sessão de exemplos nesta página.
 
=== Inserção ===
 
Ao inserir uma nova entidade no banco de dados o BISDAO simplesmente fará a inserção em cascata de todos as entidades de composição, e a associação dos IDs das entidades associadas.
 
 
=== Atualização ===
 
A atualização é uma operação um tanto mais delicada pois já temos informações persistidas no banco de dados e temos de garantir que nenhum "lixo" ficará no banco ao persistir um objeto. Inclusive desfazer relacionamentos que antes existiam e agora não existem mais, e em caso de relacionamentos de composição que deixaram de existir deve excluir os objetos filhos (deletar os objetos órfãos). Assim:
 
* O BIS atualizará os atributos da entidade como de costume;
* Atributos com relacionamento de '''composição''':
** Caso o objeto no banco ainda '''não tenha''' um relacionamento, deixamos o JPA criar a nova entidade;
** Caso o objeto no banco já '''tenha''' um relacionamento, e:
*** O novo objeto tem um relacionamento, verificamos:
**** Se ambos têm o mesmo ID, deixamos seguir para que o JPA atualize o mesmo objeto;
**** Se não tem ID, excluímos o objeto do relacionamento atual do banco e deixamos que o JPA insira o novo;
**** Se o ID for diferente, CriticalException, já que IDs não são aceitos para inserir um novo objeto!
* Atributos com relacionamento de '''associação''':
** CriticalException caso o objeto não tenha um ID definido.
 
 
Todos os relacionamentos do tipo '''composição''' serão analisados e persistidos recursivamente conforme as regras acima.
 


* '''ContactDAO:''' é uma interface que deve extender BISDefaultDAO, preenchendo seus generics com os MO e VO. Esta interface tem o objeto de separar e permitir que outras implementações de persistência funcionem de forma transparente, caso não se deseje mais utilizar o padrão EJB3DAO fornecido pelo BISCore (ou mesmo outro sistema de persistência fornecido pelo BISCore). Esta classe também não precisa ter conteúdo algum, já que sua implementação é herdada das classes do BISCore. Só terá implementação extra em objetos complexos ou que precisem de algum tipo de métodos para melhor performance ou execução de funções específicas.
{{stop|findForFullUpdate|Note que a ausência de relacionamento é tratado pelo BISDAO como "sem relacionamento" e não como "não mexer neste relacionamento". Por isso ao enviar um objeto para o BISDAO todos os relacionamentos de composição devem ser carregados recursivamente, já os relacionamentos de associação devem ser informados no mínimo com o ID do objeto.


{{java|ContactDAO|<syntaxhighlight lang="java5">
Assim, se carregar um objeto de forma incompleta e o enviar para atualizar, o BISDAO removerá as associações e ainda excluirá as composições não mais utilizadas. Um carregamento incompleto pode ocorrer por exemplo se o objeto que seja atualizado em diversas partes do sistema sofre mudanças em seus relacionamentos e em algum ponto do sistema se esquece de atualizar o método que busca o objeto no banco, causando não só um BUG como perda de dados do cliente.
public interface ContactDAO extends BISDefaultDAO<ContactVO, ContactMO> {
}
</syntaxhighlight>
}}


* '''ContactEJB3DAO:''' Esta classe e a implementação da persistência usando o modelo EJB3DAO do BISCore. Assim como as outras classes não precisa ter nenhum conteúdo especial uma vez que todo o código já está implementado nas classes do BISCore. Mas criar a classe, implementa a interface definida acima e suprir os generics necessários.
Para evitar isso sempre que obtiver um objeto para manipulação e para atualização no banco de dados '''''sempre''''' utilize o método '''findForUpdate()''' disponibilizado pelo BISDAO. Este método fará uma varredura automática no objeto e retornará sempre o objeto completo. De forma que se submetido logo em seguida para atualização nenhuma alteração será feita.}}


{{java|ContactEJB3DAO|<syntaxhighlight lang="java5">
== Mapeamentos JPA ==
public class ContactEJB3DAO extends BISDefaultEJB3DAO<ContactVO, ContactMO> implements ContactDAO {
}
</syntaxhighlight>
}}


* '''<ModuleName>DAOFactory:''' Esta classe deve ser implementada apenas uma vez no módulo, por isso não usa o nome do objeto e sim o nome do módulo. Esta classe deve ter um método implementado para criar os DAOs do objeto e retorna-lo de acordo com o sistema de persistência usado no sistema.
Esta sessão traz exemplos de como definir os mapeamentos entre as entidades para o correto funcionamento do JPA e do BISDAO.


{{java|Método de <ModuleName>DAOFactory|<syntaxhighlight lang="java5">
=== Composição ===
public static AbbreviationDAO getAbbreviationDAO() throws BISCriticalException {
  if (DAOTYPE.EJB3HIB.equals(getDaotype())) {
    return new AbbreviationEJB3DAO();
  } else {
    throw getUnsuportedDAOException();
  }
}
</syntaxhighlight>
}}


{{nota|Objetos em Cadeia|Se ContactVO contiver outros objetos (VOs) com informações, como por exemplo uma coleção de AddressVO, a camada de persistência criada para o ContactVO pode ser utilizado para realizar as operações em cadeia. Para isso precisa apenas fazer os mapeamentos do JPA entre os objetos.}}
{{nota|CascadeType.ALL|Os relacionamentos do tipo composição sempre terão o cascade em ALL. Deste modo o JPA fará a persistência em cadeia nos objetos associados.}}


{{stop|Objetos em Cadeia|Para o mesmo exemplo citado acima, um ContactVO que tenha uma coleção de AddressVO, não se deve persistir em cadeia caso o AddressVO seja um objeto autonomo, que seja cadastrado sozinho e tenha sua própria camada de persistência.
Isto é, se AddressVO for utilizado apenas por este contato, se for apenas parte do ContactVO e não for manipulado em saparado do ContactVO, este deve ser persistido junto, em cadeia pelo Hibernate, afinal, a validação do objeto assim como toda sua manipulação deverá estar implementada nos métodos de manipulação do ContactVO.
No entanto, se AddressVO é um objeto independente, que pode ser compartilhado entre outros ContactVO, cadastrado e manipulado independente do ContactVO, e para isso ter sua própria camada de persistência, ele nunca deve ser persistido junto com o ContactVO nem com outro objeto que faça referêcia. Para persisti-lo deve ser chamado o CRUD equivalente para fazer as validações e preparações necessárias antes de persisti-lo.}}


Uma vez que toda a estrutura esteja implementada, basta usar a Factory para obter a implementação correta do DAO (que será retornada apenas pela interface geral) e usar os métodos conforme descritos no JavaDoc do BISCore.
{{nota|Objeto dependente sempre tem uma relação de Associação|Note nos relacionamentos que apenas o objeto principal tem a relação definida como Composição já que é ele quem manda na persistência e existência do objeto filho/dependente. No mapeamento do objeto filho/dependente o relacionamento é definido apenas como Associação. Isso porque como ele não é o foco da existência da entidade como um todo, ele simplesmente fica associado à entidade principal.}}


== DAOFactory ==


A DAOFactory é uma a implementação do pattern Factory para a separação da camada de persistência da camada de lógica da aplicação. O pattern Factory obriga que uma única classe, aqui chamada com o sufixo Factory, implemente métodos que criem e retornem objetos identificados apenas por uma interface. Neste caso, nossa Factory é a DAOFactory, e seus métodos devem devolver as implementações dos DAOs de cada objeto de acordo com o tipo de persistência sendo utilizada. Por isso, só utilizamos uma única Factory por módulo. Esta factory terá um método para cada DAO criado no módulo. Cada DAO deve ser separado sempre em uma interface e uma ou mais implementações de acordo com a quantidade de modos de persistência que o módulo suportar.
==== OneToMany - Mapeado com Lista Ordenada ====


A classe de DAOFactory da cada módulo deve ter o nome do módulo e o sufixo DAOFactory. Devem extender a classe BISDefaultDAOFactory para herdar os métodos que informam o tipo de persistência sendo usado pelo sistema. Uma DAOFactory implementada ficaria como o código abaixo:
[[File:CompOneToMany.jpg|center|frame|OneToMany entre PersonVO.personfieldList e PersonFieldVO]]


{{java|<ModuleName>DAOFactory|<syntaxhighlight lang="java5">
{{java|PersonVO|<syntaxhighlight lang="java">
public final class BISCoreDAOFactory extends BISDefaultDAOFactory {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "personvo", fetch = FetchType.LAZY, orphanRemoval = true)
    //Métodos de getDAO() para retornar o DAO de cada objeto do módulo como mostrado na sessão anterior.
@OrderBy("indexorder")
}
@BISMetaRelationshipField(caption = "Contatos", relationship = RelationshipTypes.COMPOSITION, required = false, targetRelationship = PersonFieldVO.class)
</syntaxhighlight>
private List<PersonFieldVO> personfieldlist = null;
}}
</syntaxhighlight>}}


== BISOrderBy ==


O BISOrderBy é o objeto usado em conjunto com os MOs pela camada de persistência do BISCore para definir a ordem que os objetos devem ser retornados ao utilizarmos os métodos de find. Para criar o BISOrderBy é possível de duas maneiras: instanciando o objeto como qualquer outro, ou utilizando os métodos estáticos "getBISOrderbyInstance()".
{{java|PersonFieldVO|<syntaxhighlight lang="java">
Em ambos os casos é possível passar dois atributos: coluna a ordenar e ascendência / descendência do campo. Por padrão, se passada só o nome da coluna, a ordem será ascendente. O nome da coluna a ser passada é o mesmo nome do atributo do VO.
@ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "idperson")
@BISMetaRelationshipField(caption = "Pessoa", relationship = RelationshipTypes.ASSOCIATION, required = true)
private PersonVO personvo = null;
</syntaxhighlight>}}


Por exemplo, se temos um ClientVO, e queremos ordenar pelo atributo "name", devemos criar o BISOrderBy passando a string "name" como parâmetro. Se desejarmos que a ordem da lista seja de Z para A, devemos passar o segundo atributo como "false". Como o valor padrão é sempre true na ordem da lista, não faz sentido passar o segundo atributo para obter uma lista ascendente.
É possível organizar uma lista por um atributo que esteja em um sub VO. Por exemplo, imaginando que nosso ClientVO tenha um atributo "address" que carregue um AddressVO, e este tenha um atributo para o nome da rua chamado "street". Para ordenar a lista de clientes por nome da rua, devemos criar um BISOrderBy passando como atributo a string "address.street". Lembrando que o find a ser utilizado é de Client, e não de address.


{{nota|Criando Constantes|Um dos possíveis problemas de se passar o nome do atributo como string é um futuro refactor ou alterações do código que venham a alterar o nome da coluna/atributo do VO. Quando isso ocorre, mesmo mudando os métodos Get e Set o nome do atributo passado na String não é validado pelo builder e gerará erro de RunTime já que o atributo não será encontrado no VO.
=== Associação ===
Para evitar esse tipo de problema, recomendamos que os atributos usados comumente para ordenação da lista sejam colocados como constantes no MO. Desta forma ficam concentrados nas classes de VO as string de ordenação. Mesmo assim, nos casos de atributos em cadeia, como o nosso "address.street" não estará visível no objeto AddressMO, e sim no ClientMO.
Por isso a melhor maneira é evitar o refactor de nomes de atributos, e como evitar? Pensar bem antes de defini-los. Se não houver hipóteses e houver mesmo a necessidade de um refactor, lembre-se sempre de fazer pesquisar no código por texto com o nome do atributo.}}


Para ordenar por múltiplas colunas, basta chamar os métodos "addOrderbyItem()" e passar os mesmos atributos citados acima, ou um BISOrderBy completo. A ordem em que estes são acrescentados define a prioridade de cada coluna, ou seja, a segunda coluna só será utilizada se houver empate na primeira, a terceira só será usada de houver empate na primeira e segunda, e assim por diante.
{{nota|CascadeType.REFRESH|Os relacionamentos do tipo associação sempre terão o cascade em REFRESH. Deste modo o JPA não fará alterações no objeto associado.}}


{{java|Criando BISOrderBy|
==== ManyToOne ====
<syntaxhighlight lang="java5">
//Ordenando por uma coluna
BISOrderBy.getBISOrderbyInstance(AbbreviationMO.ORDERBY_PRIORITY);


//Ordenando por uma coluna de for descendente
[[File:AssManyToOne.jpg|center|frame|ManyToOne entre CompanyVO.locationcityvo e LocationCityVO]]
BISOrderBy.getBISOrderbyInstance(AbbreviationMO.ORDERBY_PRIORITY, false);


//Ordenando por duas colunas
{{java|CompanyVO|<syntaxhighlight lang="java">
BISOrderBy.getBISOrderbyInstance(AbbreviationMO.ORDERBY_PRIORITY, false).addOrderbyItem(AbbreviationMO.ORDERBY_OCCURENCE);
@ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.LAZY, optional = true)
@JoinColumn(name = "idcore_locationcity")
@BISMetaRelationshipField(caption = "Município", required = false, relationship = RelationshipTypes.ASSOCIATION)
private LocationCityVO locationcityvo = null;
</syntaxhighlight>}}
</syntaxhighlight>}}

Edição atual tal como às 14h41min de 23 de julho de 2018

O BISKernel oferece uma estrutura de persistência combinada com os recursos da JPA para simplificar, ou mesmo evitar, a camada de persistência dos módulos. Essa estrutura prevê métodos para insert, update, delete e "find".

Seu funcionamento compreende os seguintes itens:

  • BISVO - Um herdeiro de BISVO que represente a entidade principal a ser persistida. O objeto a ser manipulado no banco de dados.
  • BISMO - MatchObject para os métodos de find. O MatchObject representa um objeto de filtro para a busca no banco de dados.
  • BISOrderBy - Objeto usado nos métodos de find que retornam mais de 1 item para descrever a ordem dos objetos.
  • BISVO_ - O MetaObject deve ser utilizado para indicar os atributos que queremos que o método de find busque automaticamente para popular cada objeto. Normalmente os métodos de find já trazem o atributos do VO populado, mas não os atributos das entidades relacionadas (relacionamento marcados como Lazy no JPA). Quando o carregamento deste objeto for desejado o herdeiro do BISVO_ correspondente ao herdeiro do BISVO passado no construtor do BISDAO deve ser utilizado para indicar o caminho das propriedades que obrigatoriamente devem ser populadas. Em geral, se uma propriedade de um VO é solicitada todas as outras propriedades do mesmo VO que estão na mesma tabela serão poluladas automaticamente.


Padrão de Nomes
Para simplificação da programação em equipe e manutenção posterior lembre-se do padrão de nome dos objetos e classes adotados no BIS descritos no tópico Convenção de Nome do BIS.


Extensão da BISDAO
Normalmente não é necessário estender BISDAO em outra classe. Bastando a instância-la e passando a classe adequada em seu construtor os métodos padrões do BISDAO já se tornam acessíveis.

Ainda assim, é possível estender BISDAO em uma classe específica para a criação de métodos mais específicos que interagem diretamente com o JPA. Em geral estes métodos só serão necessários para ganhos de performance para métodos de consulta ou atualização do banco de dados.


Tratamento do Relacionamentos das Entidades

Este tópico relaciona o comportamento do BISDAO com às entidades relacionadas à entidade principal. Mas lembre-se que não cabe ao BISDAO realizar validações, o objeto que chega aqui deve estar pronto para ser persistido, para validar consulte o BISValidator.

O BISDAO se orienta pelas annotations do JPA e do BISMeta Annotations, logo seu correto funcionamento depende da informação correta informada nessas annotations. Veja a sessão de exemplos nesta página.

Inserção

Ao inserir uma nova entidade no banco de dados o BISDAO simplesmente fará a inserção em cascata de todos as entidades de composição, e a associação dos IDs das entidades associadas.


Atualização

A atualização é uma operação um tanto mais delicada pois já temos informações persistidas no banco de dados e temos de garantir que nenhum "lixo" ficará no banco ao persistir um objeto. Inclusive desfazer relacionamentos que antes existiam e agora não existem mais, e em caso de relacionamentos de composição que deixaram de existir deve excluir os objetos filhos (deletar os objetos órfãos). Assim:

  • O BIS atualizará os atributos da entidade como de costume;
  • Atributos com relacionamento de composição:
    • Caso o objeto no banco ainda não tenha um relacionamento, deixamos o JPA criar a nova entidade;
    • Caso o objeto no banco já tenha um relacionamento, e:
      • O novo objeto tem um relacionamento, verificamos:
        • Se ambos têm o mesmo ID, deixamos seguir para que o JPA atualize o mesmo objeto;
        • Se não tem ID, excluímos o objeto do relacionamento atual do banco e deixamos que o JPA insira o novo;
        • Se o ID for diferente, CriticalException, já que IDs não são aceitos para inserir um novo objeto!
  • Atributos com relacionamento de associação:
    • CriticalException caso o objeto não tenha um ID definido.


Todos os relacionamentos do tipo composição serão analisados e persistidos recursivamente conforme as regras acima.


findForFullUpdate
Note que a ausência de relacionamento é tratado pelo BISDAO como "sem relacionamento" e não como "não mexer neste relacionamento". Por isso ao enviar um objeto para o BISDAO todos os relacionamentos de composição devem ser carregados recursivamente, já os relacionamentos de associação devem ser informados no mínimo com o ID do objeto.

Assim, se carregar um objeto de forma incompleta e o enviar para atualizar, o BISDAO removerá as associações e ainda excluirá as composições não mais utilizadas. Um carregamento incompleto pode ocorrer por exemplo se o objeto que seja atualizado em diversas partes do sistema sofre mudanças em seus relacionamentos e em algum ponto do sistema se esquece de atualizar o método que busca o objeto no banco, causando não só um BUG como perda de dados do cliente.

Para evitar isso sempre que obtiver um objeto para manipulação e para atualização no banco de dados sempre utilize o método findForUpdate() disponibilizado pelo BISDAO. Este método fará uma varredura automática no objeto e retornará sempre o objeto completo. De forma que se submetido logo em seguida para atualização nenhuma alteração será feita.

Mapeamentos JPA

Esta sessão traz exemplos de como definir os mapeamentos entre as entidades para o correto funcionamento do JPA e do BISDAO.

Composição

CascadeType.ALL
Os relacionamentos do tipo composição sempre terão o cascade em ALL. Deste modo o JPA fará a persistência em cadeia nos objetos associados.


Objeto dependente sempre tem uma relação de Associação
Note nos relacionamentos que apenas o objeto principal tem a relação definida como Composição já que é ele quem manda na persistência e existência do objeto filho/dependente. No mapeamento do objeto filho/dependente o relacionamento é definido apenas como Associação. Isso porque como ele não é o foco da existência da entidade como um todo, ele simplesmente fica associado à entidade principal.


OneToMany - Mapeado com Lista Ordenada

OneToMany entre PersonVO.personfieldList e PersonFieldVO
PersonVO
@OneToMany(cascade = CascadeType.ALL, mappedBy = "personvo", fetch = FetchType.LAZY, orphanRemoval = true)
@OrderBy("indexorder")
@BISMetaRelationshipField(caption = "Contatos", relationship = RelationshipTypes.COMPOSITION, required = false, targetRelationship = PersonFieldVO.class)
private List<PersonFieldVO> personfieldlist = null;


PersonFieldVO
@ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "idperson")
@BISMetaRelationshipField(caption = "Pessoa", relationship = RelationshipTypes.ASSOCIATION, required = true)
private PersonVO personvo = null;


Associação

CascadeType.REFRESH
Os relacionamentos do tipo associação sempre terão o cascade em REFRESH. Deste modo o JPA não fará alterações no objeto associado.

ManyToOne

ManyToOne entre CompanyVO.locationcityvo e LocationCityVO
CompanyVO
@ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.LAZY, optional = true)
@JoinColumn(name = "idcore_locationcity")
@BISMetaRelationshipField(caption = "Município", required = false, relationship = RelationshipTypes.ASSOCIATION)
private LocationCityVO locationcityvo = null;