Processamento de banco de dados baseado na ideia ORM

[iOS] Processamento de banco de dados baseado em ideias ORM

Este artigo apresenta principalmente a solução de armazenamento de banco de dados no iOS e usa ORM para encapsular o FMDB para tornar o código mais conciso e conveniente.

Em primeiro lugar, o problema de desenvolvimento de banco de dados
com o pacote FMDB para o sqlite, operações de banco de dados iOS final é bastante fácil, não temos mais que enfrentar esses problemas e sqlite ovo de dor de moagem de thread. No entanto, ainda é inevitável encontrar algumas dores de ovo no desenvolvimento real.

  • (void) createPaintTable {
    [self.db executeUpdate: @ ”CREATE TABLE paint_table (paintID varchar (32),
    answerercount int, create_timestamp double, last_modified_time double,
    imgwidth int, imgheight int, imgurl varchar (256), last_reply_user_id
    varchar (32), text varchar (512), money int, questype int, replytype int,
    user_id varchar (32), viewcount int, commentcount int, supportcount int,
    author_id varchar (32), replyAuthor_id varchar (32), accept_user_id
    varchar (32)) ”] ;

    [self checkError]; }

Isso é simplesmente criar uma tabela, acho que você vai ficar louco ao ver esse código. Porém, o que enlouquece as pessoas é que um dia precisamos adicionar um campo por causa da demanda do produto, depois temos que alterá-lo em vários lugares. E, uma vez que a atualização do banco de dados não seja tratada adequadamente devido a negligência, pode causar um acidente online muito sério. (É uma pena ter encontrado este tipo de acidente)

2. Como resolver este problema

2.1 Armazenamento de valor-chave -
A tabela de dados do cliente YTKKeyValueStore iOS geralmente precisa corresponder a um modelo, o que leva à necessidade de adicionar uma camada de conversão de modelo ao usá-lo, e o terminal móvel não tem altos requisitos para consultas de banco de dados Para essas características, surgiu o armazenamento no estilo Key-Value. Uma estrutura representativa é YTKKeyValueStore de Yuantiku (a ideia principal é serializar o modelo de dados como um armazenamento de valor). Mas as falhas desse tipo de estrutura são bastante óbvias, apenas por meio da consulta de chave principal. E se o modelo mudar, o processamento de atualização de dados só pode ser processado durante a conversão do modelo. O armazenamento de valor-chave não pode mais ser chamado de armazenamento de banco de dados, é um produto especial produzido de acordo com as necessidades especiais do cliente, o banco de dados é apenas um recipiente para ele.

2.2 Estrutura ORM-GYDataCenter A estrutura
ORM (Object Relational Mapping) usa metadados para descrever os detalhes do mapeamento objeto-relacional.Os metadados estão geralmente no formato XML e armazenados em um arquivo especial de objeto para mapeamento. Contanto que o relacionamento de mapeamento entre classes e tabelas persistentes seja fornecido, a estrutura ORM pode consultar as informações no arquivo de mapeamento no tempo de execução para persistir objetos no banco de dados. Atualmente, existem quatro estruturas ORM principais: Hibernate (Nhibernate), iBATIS, mybatis e EclipseLink.

O texto acima é a explicação da Enciclopédia Baidu da estrutura ORM. Preste atenção às duas palavras-chave que marquei, tempo de execução e objeto. A essência do armazenamento de banco de dados do cliente iOS é armazenar um objeto no banco de dados, e OC também é um runtime language., O que temos que fazer é criar um arquivo de mapeamento, consultar o arquivo de mapeamento para gerar a instrução SQL correspondente em tempo de execução e salvar o objeto no banco de dados.

Acho que muitos alunos estão familiarizados com o framework do MLeaksFinder, que usa uma maneira muito inteligente que nos permite encontrar facilmente vazamentos de memória no modo DEBUG. Hoje, quando visitei o gitHub do autor Zepo, descobri que ele escreveu outra estrutura, GYDataCenter. Eu brevemente olhei para ela como uma solução de armazenamento de banco de dados cliente iOS escrita usando ideias ORM, que coincidiram com a minha ideia.

Não olhei o código-fonte do GYDataCenter, apenas fiz algumas perguntas com base em como ele foi usado. O relacionamento de mapeamento de GYDataCenter é fornecido pelo método correspondente fornecido por GYModelObject, e o método correspondente deve ser implementado herdando GYModelObject. Ou seja, o autor combinou a relação de mapeamento com o modelo de objeto na classe GYModelObject, resultando no acoplamento. Esse acoplamento causará alguns problemas. Existem muitos lugares onde o modelo é usado no projeto. A conversão do modelo, a exibição da visualização e o processamento de dados envolvem o modelo. Adicionar a relação de mapeamento ao modelo pode facilmente causar o inchaço do modelo. O uso de herança também o torna muito invasivo. Portanto, o relacionamento de mapeamento deve existir independentemente do modelo de objeto.

Três, JYDatabase (é sobre isso que eu quero falar ...)
JYDatabase Este é um framework de aplicativo de banco de dados que escrevi baseado em idéias ORM, e também é baseado na implementação de FMDB como GYDataCenter. O seguinte fala principalmente sobre a implementação do framework e usar.

3.1 Problemas a serem resolvidos
1. Gerenciar atualizações de banco de dados automaticamente para que os usuários não precisem se preocupar com os problemas causados ​​por atualizações de banco de dados.
2. Encapsular instruções de consulta simples e comumente usadas, de modo que os usuários só precisem prestar atenção a consultas SQL especiais, sem serem torturados por instruções SQL dolorosas.

3.2 O estabelecimento da tabela de dados (o estabelecimento da relação de mapeamento) O estabelecimento da
tabela de dados precisa herdar JYContentTable (esta classe implementa a maioria das consultas SQL usadas no trabalho), contanto que você reescreva os métodos a seguir, pode criar rapidamente uma tabela de dados.

// Deve implementar contentClass é a classe do modelo correspondente à tabela, tableName é o nome da tabela

  - (void)configTableName{             
     self.contentClass = [JYPersonInfo class];
     self.tableName = @"JYPersonTable";
  }

// Deve-se perceber que contentId é a chave primária (e também o único índice) da tabela. Por exemplo, o userId do usuário deve ser um atributo de contentClass

  - (NSString *)contentId{
      return @"personnumber";
  }

// Outros campos da tabela de dados devem ser atributos de contentClass, se não implementados, os atributos cujo contentClass termina com "DB" são considerados por padrão

  - (NSArray<NSString *> *)getContentField{
      return @[@"mutableString1",@"integer1",@"uInteger1",@"int1",@"bool1",@"double1"];
  }

// O comprimento padrão do campo correspondente quando a tabela é criada, se não for escrita, o comprimento padrão é usado.

  - (NSDictionary*)fieldLenght{
        return @[@"mutableString1":@"512"];
  }

// Consultar se deseja usar o cache NSCache, o padrão é SIM.

  - (BOOL)enableCache{
      return NO;
  }

Nota: 1. Os atributos do mapeamento da tabela de dados suportam NSString NSMutableString NSInteger NSUInteger int BOOL double float NSData e outros tipos de dados, como segue:

NSDictionary * jy_correspondingDic () {
return @ {@ ”Tb”: @ ”BOOL”,
@ ”TB”: @ ”BOOL”,
@ ”Tc”: @ ”BOOL”,
@ ”TC”: @ ”BOOL”,
@ ”Td”: @ ”DOUBLE”,
@ ”TD”: @ ”DOUBLE”,
@ ”Tf”: @ ”FLOAT”,
@ ”TF”: @ ”INTEGER”,
@ ”Ti”: @ ”INTEGER”,
@ ”TI”: @ ”INTEGER”,
@ ”Tq”: @ ”INTEGER”,
@ ”TQ”: @ ”INTEGER”,
@ ”T @ \” NSMutableString \ ”“: @ ”VARCHAR”,
@ ”T @ \ ”NSString \” “: @” VARCHAR ”,
@” T @ \ ”NSData \” “: @” BLOB ”,
@” T @ \ ”UIImage \” “: @” BLOB ”,
@” T @ \ ”NSNumber \ ”“: @ ”BLOB”,
@ ”T @ \” NSDictionary \ ”“: @ ”BLOB”,
@ ”T @ \” NSMutableDictionary \ ”“: @ ”BLOB”,
@ ”T @ \” NSMutableArray \ ” “: @” BLOB ”,
@” T @ \ ”NSArray \” “: @” BLOB ”,};
}

2. O cache padrão do NSCache é o número 20, pode ser fornecido para modificar seu próprio self.cache.countLimit = 20; enableCache usa dados de busca de prioridade do cache
, como consultas autorrealizáveis, use os três métodos a seguir, quando apropriado, para adicionar Cache. Há uma implementação de enableCache dentro do método.


- (id)getCacheContentID:(NSString *)aID;
  - (void)saveCacheContent:(id)aContent;
  - (void)removeCacheContentID:(NSString *)aID;

3.3 Criação de banco de dados e gerenciamento de atualização
3.3.1 A classe de criação de banco de dados e gerenciamento de atualização precisa herdar JYDataBase

Método chave:

// Este método determinará se deve criar uma tabela de banco de dados ou uma atualização de tabela de dados com base na versão atual

- (void)buildWithPath:(NSString *)aPath mode:(ArtDatabaseMode)aMode;

// Retorne à versão atual do banco de dados, desde que a tabela de dados seja modificada, retorne o número da versão, por favor, +1 e retorne 1 por padrão

  • (NSInteger) getCurrentDBVersion {
    return 4;
    }

// Para criar todas as tabelas de dados, chame o método fixo neste método- (void) createTable: (FMDatabase *) aDB ;-(
void) createAllTable: (FMDatabase *) aDB {
[self.personTable createTable: aDB];
}

// Para atualizar todas as tabelas de dados, chame o método fixo neste método-

(void)insertDefaultData:(FMDatabase *)aDb;
- (void)updateDB:(FMDatabase *)aDB{
    [self.personTable updateDB:aDB];
}

3.3.2 Implementação de atualização de banco de dados- (void) updateDB: (FMDatabase *) aDB

Para cada tabela, a chamada modificação nada mais é do que adicionar um novo campo ou reduzir alguns campos (isso é raro).

  1. O campo de contraste de
    PRAGMA table_info ([tableName]) pode obter uma lista de todos os campos
    e então fazer os campos obrigatórios do campo atual e o contraste pode ser obtido reduzindo o campo a ser aumentado

  2. Adicionando campos
    SQLite fornece instruções SQL correspondentes para atingir o
    tipo de campo ALTER TABLE tableName ADD (comprimento)

  3. Reduzir o campo
    sqlite não fornece a implementação de instrução SQL correspondente, mas pode ser obtido pelos seguintes métodos
    a. Crie uma nova tabela com base na tabela original
    sql = [NSString stringWithFormat: @ ”criar tabela% @ como selecionar% @% @ from% @ ”, tempTableName, [self contentId], tableField, self.tableName];
    b. Excluir a tabela original
    sql = [NSString stringWithFormat: @” eliminar tabela se existir% @ ”, self.tableName];
    c. Renomear o tabela
    sql = [NSString stringWithFormat: @ ”Alterar tabela% @ renomear para% @”, tempTableName, self.tableName];

    d. Adicione um índice exclusivo para a nova tabela

     sql = [NSString stringWithFormat:@"create unique index '%@_key' on  %@(%@)", self.tableName,self.tableName,[self contentId]];

3.4 As condições
geram uma consulta sobre consultas complexas. Eu forneço uma maneira simples

- (NSArray *)getContentByConditions:(void (^)(JYQueryConditions *make))block;

Você pode ver seu uso

NSArray*infos = [[JYDBService shared] getPersonInfoByConditions:^(JYQueryConditions *make) {
    make.field(@"personnumber").greaterThanOrEqualTo(@"12345620");
    make.field(@"bool1").equalTo(@"1");
    make.field(@"personnumber").lessTo(@"12345630");
    make.asc(@"bool1").desc(@"int1");
}];

Na verdade, ele produziu apenas a seguinte consulta:

SELECT * FROM JYPersonTable WHERE personnumber >= 12345620 AND bool1 = 1 AND personnumber < 12345630  order by  bool1 asc , int1 desc 

make.field(@"personnumber").greaterThanOrEqualTo(@"12345620"); 就代表了 personnumber >= 12345620

A implementação é realmente muito simples, primeiro use JYQueryConditions para registrar os parâmetros descritos e, finalmente, emendar a instrução SQL completa.
Quanto à chamada em cadeia através da sintaxe de pontos, refere-se ao método de declaração da Maçonaria

- (JYQueryConditions * (^)(NSString *compare))equalTo;
- (JYQueryConditions * (^)(NSString *field))field{
return ^id(NSString *field) {
    NSMutableDictionary *dicM = [[NSMutableDictionary alloc] init];
    dicM[kField] = field;
    [self.conditions addObject:dicM];
    return self;
};
}

Quarto, terminando
em JYDatabase use e introduza todos podem ir para ver uma descrição mais detalhada do gitHub

https://github.com/weijingyunIOS/JYDatabase , sobre a estrutura apresentada acima, você pode escolher usá-la depois de compará-la de acordo com as necessidades reais. GYDataCenter é uma solução de processamento de banco de dados muito boa. Se sair antes ou eu vir antes, talvez eu não gaste muito esforço para escrever JYDatabase, mas escrever JYDatabase também é muito agradável porque sua direção de pensamento é baseada no pontos problemáticos que encontrei. Para escrever, como consulta sql, porque a instrução sql pode não ser executada devido a um problema de espaço em uma posição-chave, então escrevi um JYQueryConditions para enfraquecer o sql.

Acho que você gosta

Origin blog.csdn.net/woruosuifenglang/article/details/71171667
Recomendado
Clasificación