BISDAO

De BIS Wiki
Ir para navegação Ir para pesquisar

A persistência do BIS é automatizada como um sistema de ORM automático, mas melhor definido para as necessidades de Patterns do BIS. Gerando menos problemas de persistência, mais autonomia no desenvolvimento e praticidade na maior parte das tarefas que envolvem o banco de dados.

O principal objetivo do BISDAO é receber objetos e persisti-lo (inserindo/atualizando), exclui-lo ou encontrar os objetos no banco de dados automaticamente. Abstraindo a questão objeto x relacional do banco de dados, e diminuindo (ou eliminando na maioria dos casos) a necessidade de implementação códigos SQL pelo desenvolvedor.

Regras do Funcionamento

  1. Embora utilize os conceitos do banco de dados (por óbvio já que utiliza um banco dados), não segue os padrões definidos no JPA. Assim, nenhuma annotation do JPA é utilizada nas entidades do BIS.
  1. O BISDAO manipula os objetos/entidades padrão do BIS automaticamente, isto é, para ser persistido é necessário que a entidade seja descendente do BISVO.

Estrutura do Banco de Dados

O BIS é uma plataforma que suporta múltiplas empresas sendo manipuladas pela mesmas instância. Assim um mesmo servidor e mesmo banco de dados será utilizado para gerenciar várias empresas. Para isso o sistema utilizará vários "schemas" (ou catálogos) do banco de dados, sendo:

  • bis_kernel - schema onde ficam as tabelas de uso geral do sistema. Como o cadastro das empresas presentes, dos usuários de sistema, e outras tabelas de dados comuns a todas as empresas, como tabelas de CEP, e outros dados que não pertencem a uma única empresa.
  • bis_<empresa> - com este nome deve existir um schema para cada empresa que o sistema gerencia. Isto é, para cada empresa que o BIS atender, um novo schema é criado para armazenar os dados específicos da empresa, como itens/produtos sendo vendidos, documentos fiscais, etc.

Configuração das FK

Ao criar a associação entre as tabelas do banco de dados devemos seguir as seguintes regras para o bom funcionamento do BISDAO:


Relacionamento tipo Associação

  1. No relacionamento não obrigatório devemos colocar as opções ON DELETE SET TO NULL (nos relacionamentos 1:1 ou 1:N) e ON DELETE CASCADE (nos relacionamentos N:N, para que se exclua o registro na tabela de join).
    O BISDAO não faz essa atualização para NULL para desmanchar o relacionamento antes de excluir o objeto. A ausência dessa configuração fará com que o objeto não possa ser excluído pelo BIS quando utilizado por outro objeto.
  2. No relacionamento obrigatório devemos colocar as opções ON DELETE RETRICT. Nos relacionamentos N:N podemos colocar para "restringir" de um lado mas para "cascata" de acordo com a condição de obrigatoriedade do relacionamento.
    Como o relacionamento é obrigatório (dependente) para a contra parte, a deleção deve ser restringida de propósito. Isso porque o BISDAO não procura objetos que dependam deste antes de excluir. O Banco de Dados fica responsável por restringir essa operação.


Relacionamento tipo Composição

  1. No caso de composição devemos sempre definir a opção ON DELETE CASCADE já que o objeto filho não existe sem o pai e não deve restringir a exclusão do pai.


ON UPDATE CASCADE
Em caso de update, sempre vamos utilizar a opção do 'CASCADE'. Embora o BIS não faça alteração do ID dos objetos, pode ser necessário corrigir algum ID diretamente no banco de dados (migração, bug, merge, etc).


Relacionamentos N:N UniqueIndex
Normalmente em relacionamentos N:N as colunas do relacionamento são a própria PrimaryKey da tabela, o que já evita a inserção de múltiplas entradas. É importante que sejam definidas como PrimaryKey ou coloque uma constante de UniqueIndex para que em caso de inserção de duplicada dos registros de associação termine em erro. Permitindo que o desenvolvedor detecte e corrija.


Relacionamento Entre Objetos

Os relacionamentos entre objetos serão declarados de acordo com o "tipo do relacionamento" constituído entre eles para que o BISDAO saiba como proceder quando for atualizar, inserir ou excluir os objetos. Entender o relacionamento entre os dois define a boa arquitetura ao criar os objetos:

Associação

O tipo de relacionamento Associação é utilizando quando ambos os objetos existem separadamente, mesmo que não tenham vínculos. Por exemplo:

  • Aluno x Curso - Tanto Aluno quando Curso existem estando o aluno matriculado no curso ou não. Um curso pode existir sem ter nenhum aluno matriculado, bem como um Aluno pode existir sem estar matriculado em nenhum curto.

Para o BISDAO, esse tipo de relacionamento exige que a contra-parte já exista no banco de dados, ou seja já tenha um ID. A contra parte nunca é manipulada junto com este objeto, ou seja:

  • Exclusão - O objeto da contra-parte não é excluído junto, apenas a associação é desfeita.
  • Inclusão - Em caso de inclusão, o BISDAO espera que os objetos associados já tenham um ID. Pois eles não serão incluídos junto, apenas será criada uma associação.
  • Alteração - Em caso de alteração o objeto será comparado com o atual no banco de dados. Objetos que não estejam mais presentes no objeto sendo persistido, terão sua associação removida, novos objetos terão associação criada. A contra-parte nunca será excluída, e nem criada.

Composição

O relacionamento do tipo composição indica que o objeto associação é uma "extensão" deste objeto. Ou seja, ele faz parte do objeto principal, e como tal será manipulando junto com o objeto pai. Por exemplo:

  • Pessoas x Endereços da Pessoa - Pessoas pode existir sem ter um endereço, já o endereço da pessoa não existe sem a pessoa. Neste caso, "Endereços da Pessoa" é parte do objeto pai e será manipulado junto com ele.

Para o BISDAO a contra-parte pode ou não existir no banco de dados nos casos de alteração do objeto pai, mas no caso de inclusão do pai o objeto filho não deve ter ID (ou seja, não existe no banco). Mesmo que Pessoas diferentes tenham o mesmo Endereço, o BIS não permitirá compartilhar o mesmo objeto. Uma vez que a definição de composição não permite que o "reaproveitamento" do objeto. Para isso Endereço de Pessoa teria de ser uma entidade autônoma (existir sem o Pessoas) e o relacionamento deveria ser o de Associação. Neste caso a contra-parte é manipulada junto com o pai:

  • Exclusão - Quando o objeto pai é excluído os objetos filhos serão excluídos junto.
  • Inclusão - Em caso de inclusão, os objetos filhos serão incluídos juntos e automaticamente associados ao objeto pai.
  • Alteração - Em caso de alteração do objeto pai, novos objetos filhos serão incluídos e persistidos, objetos filhos que foram removidos do objeto serão excluídos automaticamente. Bem como as informações dos objetos filhos persistentes também serão atualizadas em cascata, isto é, caso esse objeto também tenha outros de composição ou associação, eles também serão atualizados.


Annotation @BISDAO

Toda entidade deve ter a Class Annotation @BISDAO para configurar a tabela a qual o objeto se refere.

Exemplo @BISDAO
@BISDAO(schemaType = Schema.KERNEL, table = "k_company")
public class BISCompanyVO extends BISVO {
   ...
}

A annotation tem dois parâmetros:

  • schemaType - Indica se a tabela pertence ao Schema do Kernel do BIS ou ao Schema da empresa.
  • table - Indica o nome da tabela onde o conteúdo deste objeto é guardado.

Relacionamento Atributo do Objeto x Coluna do BD

Para que um atributo do objeto seja relacionado corretamente com uma coluna da tabela (especificada na Annotation @BISDAO) é necessário que o atributo tenha uma @BISMeta Annotations. Nela constarão várias informações sobre o atributo, incluindo a coluna. Caso o nome da coluna não seja especificado, o BISDAO assume que o nome da coluna é exatamente o mesmo nome do atributo, ou seja, caso o mesmo nome seja utilizado na coluna do banco quando no atributo do objeto, não é necessário especificar o atributo coluna na Annotation. Isso deixa o código menos poluído.


Mapeamento do Relacionamento

O mapeamento de todos os relacionamentos são feitos através da @BISMetaRelationshipField.

Associação 1:1

Associação 1:N

Associação OneToMany entre BISCompanyVO e BISFileVO

A associação 1:N do exemplo é unilateral, já que só o FileVO tem conhecimento do vínculo. A descrição do mapeamento feito no FileVO é a mesma utilizada em uma associação 1:1.

FileVO
  @BISMetaRelationshipField(column = "k_company_id", required = true, relationship = RelationshipTypes.ASSOCIATION, ...)
  private BISCompanyVO companyVO = null;

Sendo os atributos:

  • relationship - Definido como ASSOCIATION para indicar a associação (tanto para 1:N quanto 1:1).
  • column - nome da coluna que tem o ID da entidade associada. Utilizado somente se a coluna com o ID estiver na tabela desta entidade.
  • columnMapped - nome da coluna que tem o ID do objeto da contra-parte. Utilizado somente se a coluna com o ID desta entidade (FK) estiver na tabela da entidade associada.
  • targetRelacionship - Classe do objeto utilizado na contra-parte. Normalmente a mesma classe passada no "generics" da coleção. Quando não é uma coleção de objeto, este atributo pode ser omitido e será usado o próprio tipo do Field declarado na classe. Neste caso o BISCompanyVO.


Associação N:N

Associação ManyToMany entre BISCompanyVO e BISUserVO

A associação N:N (Many To Many) exige uma tabela intermediária para gravar as associações. Nos objetos o relacionamento é feito da seguinte maneira:


BISCompanyVO
  @BISMetaRelationshipField(relationship = RelationshipTypes.MANY_TO_MANY, joinTable = "k_user_company", column = "k_company_id", columnMapped = "k_user_id", targetRelationship = BISUserVO.class, ...)
  private List<BISUserVO> users = null;


BISUserVO
  @BISMetaRelationshipField(relationship = RelationshipTypes.MANY_TO_MANY, joinTable = "k_user_company", column = "k_user_id", columnMapped = "k_company_id", targetRelationship = BISCompanyVO.class, ...)
  private List<BISCompanyVO> companies = null;


Sendo os atributos:

  • relationship - Em ambas as entidades definido como MANY_TO_MANY para indicar a associação de N:N.
  • joinTable - Nome da tabela de join entre as tabelas dos objetos.
  • column - nome da coluna que tem o ID da entidade onde está a declaração.
  • columnMapped - nome da coluna que tem o ID do objeto da contra-parte.
  • targetRelacionship - Classe do objeto utilizado na contra-parte. Normalmente a mesma classe passada no "generics" da coleção.


Schema da Tabela de Join
A tabela de join é procurada dentro do mesmo schema da entidade pai. Ou seja a entidade que declara o BISMetaRelationshipField.

Quando há relacionamento entre tabelas do schema da empresa e do schema do kernel, a entidade do kernel não conhece o relacionamento, logo ela não declara o relacionamento.

Além disso, o relacionamento entre tabelas da empresa só pode estar dentro do schema da empresa, caso contrário a tabela de join teria de ter uma coluna para cada tabela de schema diferente. Completamente impossível.

Composição 1:1

Composição 1:N

Composição N:N

O BIS não permite esse tipo de composição. Isso porque esse relacionamento indica o reaproveitamento dos objetos filhos por outros pais. Neste caso o objeto filho deve ter sua "autonomia" e viver independente do pai. Casos como esses devem ser transformados em Associação N:N.