Compile time processed, annotation driven, no reflection SQLite database layer for Android

Overview

SqliteMagic

Simple yet powerful SQLite database layer for Android that makes database handling feel like magic.

Overview:

  • Simple, intuitive & typesafe API
  • Minimal setup needed
  • Built in RxJava support with reactive stream semantics on queries and operations
  • Built in AutoValue immutable objects support
  • Built in kotlin support
  • Full support for complex columns
  • Support for SQLite views
  • Persist any third party object with fully customizable object transformers
  • Support for migrations
  • No reflection
  • Compile time annotation processing
  • Probably the fastest library for Android SQLite database operations (without memory caching)

Getting Started

Install IntelliJ Plugin (for non-kotlin project):

The Intellij plugin can be installed from Android Studio by navigating Android Studio -> Preferences -> Plugins -> Browse repositories -> Search for SqliteMagic

Add SqliteMagic to Project:

buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:<latest version>'
    classpath 'com.siimkinks.sqlitemagic:sqlitemagic-plugin:0.25.1'
  }
}

apply plugin: 'com.android.application'
apply plugin: 'com.siimkinks.sqlitemagic'

Initialize Library:

SqliteMagic.builder(applicationContext)
    .sqliteFactory(new FrameworkSQLiteOpenHelperFactory())
    .openDefaultConnection();

Note: any place with a reference to Application context is ok to use for initialization, but it must happen before a database is accessed. During initialization default db connection is opened, db schema is created and migration scripts are executed - no other hidden runtime performance costs.

Define Database:

Note that there is no need to extend or implement any base classes or interfaces

POJO AutoValue
@Table(persistAll = true)
public class Author {

  @Id(autoIncrement = false)
  long id;
  
  String firstName;
  
  String lastName;
  
  ...
}



@Table(persistAll = true)
public class Book {

  @Id(autoIncrement = false)
  long id();
  
  String title;
  
  Author author;
  
  ...
}

@Table(persistAll = true)
@AutoValue
public abstract class Author {

  @Id(autoIncrement = false)
  public abstract long id();
  
  public abstract String firstName();
  
  public abstract String lastName();
  
  ...
}

@Table(persistAll = true)
@AutoValue
public abstract class Book {

  @Id(autoIncrement = false)
  public abstract long id();
  
  public abstract String title();
  
  public abstract Author author();
  
  ...
}
Kotlin
@Table(persistAll = true, useAccessMethods = true)
data class Author(
  @Id(autoIncrement = false) val id: Long,
  val firstName: String,
  val lastName: String
)



@Table(persistAll = true, useAccessMethods = true)
data class Book(
  @Id(autoIncrement = false) val id: Long,
  val title: String,
  val author: Author
)

Database operation builder methods for Java are "automagically" generated during compile time on objects with @Table annotation using bytecode manipulation and AST transformations. These methods may seem like "magic", but actually they are only glue methods that call corresponding table generated class methods. This way one can still see human readable code during debugging - just press "step into" when magic method is encountered.

For kotlin, database operation builder methods are generated as extensions functions.

Do Operations With Objects:

Synchronous RxJava
Author author = new Author(73, "Foo", "Bar");
Book book = new Book(77, "Bar", author);

// insert -- NOTE: author object also gets
// inserted and the whole operation
// is wrapped in transaction
long id = book
    .insert()
    .execute();

// update
boolean success = author
    .update()
    .execute();

// update or insert
id = author
    .persist()
    .execute();
    
// update or insert but ignore null values
id = author
    .persist()
    .ignoreNullValues()
    .execute();
    
// delete
int nrOfDeletedRows = author
    .delete()
    .execute();
    
// Bulk operations are also supported
success = Author
    .persist(someAuthors)
    .ignoreNullValues()
    .execute();
Author author = new Author(73, "Foo", "Bar");
Book book = new Book(77, "Bar", author);

// insert -- NOTE: author object also gets
// inserted and the whole operation is
// wrapped in transaction when result
// object gets subscribed
Single<Long> insert = book
    .insert()
    .observe();

// update
Completable update = author
    .update()
    .observe();

// update or insert
Single<Long> persist = author
    .persist()
    .observe();
    
// update or insert but ignore null values
persist = author
    .persist()
    .ignoreNullValues()
    .observe();
    
// delete
Single<Integer> delete = author
    .delete()
    .observe();
    
// Bulk operations are also supported
Completable bulkPersist = Author
    .persist(someAuthors)
    .ignoreNullValues()
    .observe();

(All database operations trigger RxJava notifications on active queries that listen to table that is being modified)

Use Typesafe Operation Builders:

Synchronous RxJava
import static com.siimkinks.sqlitemagic
    .BookTable.BOOK;
...

int nrOfUpdatedRows = Update
    .table(BOOK)
    .set(BOOK.TITLE, "Foo")
    .where(BOOK.ID.is(77L))
    .execute();

int nrOfDeletedRows = Delete
    .from(BOOK)
    .where(BOOK.ID.isNot(77L)
        .and(BOOK.TITLE.is("Foo")))
    .execute();
import static com.siimkinks.sqlitemagic
    .BookTable.BOOK;
...

Single<Integer> update = Update
    .table(BOOK)
    .set(BOOK.TITLE, "Foo")
    .where(BOOK.ID.is(77L))
    .observe();

Single<Integer> delete = Delete
    .from(BOOK)
    .where(BOOK.ID.isNot(77L)
        .and(BOOK.TITLE.is("Foo")))
    .observe();

Query Data:

SqliteMagic ships with its own DSL (or Domain Specific Language) that emulates SQL in Java (inspired by JOOQ).

Synchronous RxJava
import static com.siimkinks.sqlitemagic
    .AuthorTable.AUTHOR;
...

List<Author> authors = Select
    .from(AUTHOR)
    .where(AUTHOR.FIRST_NAME.like("Foo%")
        .and(AUTHOR.LAST_NAME.isNot("Bar")))
    .orderBy(AUTHOR.LAST_NAME.desc())
    .limit(10)
    .execute();

import static com.siimkinks.sqlitemagic
    .AuthorTable.AUTHOR;
...

// QueryObservable is an rx.Observable of Query
// which offers query-specific convenience
// operators.
QueryObservable<List<Author>> observable = Select
    .from(AUTHOR)
    .where(AUTHOR.FIRST_NAME.like("Foo%")
        .and(AUTHOR.LAST_NAME.isNot("Bar")))
    .orderBy(AUTHOR.LAST_NAME.desc())
    .limit(10)
    .observe();

Query Complex Data:

Synchronous RxJava
import static com.siimkinks.sqlitemagic
    .AuthorTable.AUTHOR;
import static com.siimkinks.sqlitemagic
    .BookTable.BOOK;
...

// the resulting Book objects also contain
// Author objects
List<Book> books = Select
    .from(BOOK)
    .where(BOOK.TITLE.is("Bar")
        .and(AUTHOR.is(someAuthorObject)))
    .orderBy(AUTHOR.LAST_NAME.asc())
    .limit(10)
    // this tells to query all complex data
    // which is queried in a single
    // SELECT statement
    .queryDeep()
    .execute();
import static com.siimkinks.sqlitemagic
    .AuthorTable.AUTHOR;
import static com.siimkinks.sqlitemagic
    .BookTable.BOOK;
...

// the resulting Book objects also contain
// Author objects
QueryObservable<List<Book>> observable = Select
    .from(BOOK)
    .where(BOOK.TITLE.is("Bar")
        .and(AUTHOR.is(someAuthorObject)))
    .orderBy(AUTHOR.LAST_NAME.asc())
    .limit(10)
    // this tells to query all complex data
    // which is queried in a single
    // SELECT statement
    .queryDeep()
    .observe();

There is so much more to querying data like SQL functions, views, more type safety, selecting columns, querying only the first result, counting, RxJava convenience operators, etc. Take a deeper look at the wiki.

Documentation

Updates

All updates can be found in the CHANGELOG.

Bugs and Feedback

For bugs, questions and discussions please use the Github Issues.

License

Copyright 2020 Siim Kinks

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • What could it be the issue here, as I'm only receiving one specific device with issue & it happens when querying a single row.

    What could it be the issue here, as I'm only receiving one specific device with issue & it happens when querying a single row.

    Exception java.lang.IllegalStateException: newPosition should be in the window at this point
    
    android.database.sqlite.SQLiteCursor.onMove (SQLiteCursor.java:133)
    
    
    
    
    opened by k0shk0sh 5
  • Lombok issue

    Lombok issue

    Hello There, well first of all, Thanks for the library, i'm sad that it isn't that famous which it should, however i have an issue where it comes to lombok below is the log and couldn't really figure out whats going on. Lombok works fine before i add your library as a dependency.

    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:411)
    at lombok.launch.ShadowClassLoader.loadClass(ShadowClassLoader.java:418)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at lombok.core.SpiLoadUtil$1$1.next(SpiLoadUtil.java:111)
    at lombok.javac.HandlerLibrary.loadAnnotationHandlers(HandlerLibrary.java:170)
    at lombok.javac.HandlerLibrary.load(HandlerLibrary.java:155)
    at lombok.javac.JavacTransformer.<init>(JavacTransformer.java:43)
    at lombok.javac.apt.Processor.init(Processor.java:86)
    at lombok.core.AnnotationProcessor$JavacDescriptor.want(AnnotationProcessor.java:87)
    at lombok.core.AnnotationProcessor.init(AnnotationProcessor.java:141)
    at lombok.launch.AnnotationProcessorHider$AnnotationProcessor.init(AnnotationProcessor.java:53)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment$ProcessorState.<init>(JavacProcessingEnvironment.java:500)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:597)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:690)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176)
    at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170)
    at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856)
    at com.sun.tools.javac.main.Main.compile(Main.java:523)
    at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129)
    at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138)
    at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:46)
    at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:33)
    at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.delegateAndHandleErrors(NormalizingJavaCompiler.java:104)
    at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:53)
    at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:38)
    at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:35)
    at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:25)
    at org.gradle.api.tasks.compile.JavaCompile.performCompilation(JavaCompile.java:206)
    at org.gradle.api.tasks.compile.JavaCompile.compile(JavaCompile.java:187)
    at org.gradle.api.tasks.compile.JavaCompile.compile(JavaCompile.java:130)
    at com.android.build.gradle.tasks.factory.AndroidJavaCompile.compile(AndroidJavaCompile.java:49)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
    at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$IncrementalTaskAction.doExecute(DefaultTaskClassInfoStore.java:163)
    at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:134)
    at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:123)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:95)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:76)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:55)
    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:62)
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:88)
    at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:46)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:51)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.execute(DefaultTaskGraphExecuter.java:236)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.execute(DefaultTaskGraphExecuter.java:228)
    at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:61)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:228)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:215)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:77)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:58)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
    at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
    Caused by: java.lang.ClassNotFoundException: lombok.javac.JavacAnnotationHandler
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 78 more```
    opened by k0shk0sh 4
  • How to handle a list of string

    How to handle a list of string

    Currently, I have the following field in my entity

    @Table(persistAll = true, value = "table_movie") @AutoValue public abstract class MovieEntity {
    
      @Id @Column(value = "movie_id") public abstract long id();
    
      @Column(value = "movie_name") public abstract String name();
    
      @Column(value = "category") public abstract CategoryEntity category();
    
      @Column(value = "alt_names") public abstract List<String> alternativeNames();
    }
    

    I have added a Transformer class for List String that convert into JSON vice versa.

    @Transformer public class StringListTransformer {
    
      @ObjectToDbValue public static String objectToDBValue(List<String> object) {
        return new Gson().toJson(object);
      }
    
      @DbValueToObject public static List<String> dbValueToObject(String dbValue) {
        return new Gson().fromJson(dbValue, new TypeToken<List<String>>() {
        }.getType());
      }
    }
    

    When I compile my project it gave out this error with no instructions to recover

    Error:Execution failed for task ':sqlitemagic:compileDebugJavaWithJavac'. java.lang.ClassCastException: com.sun.tools.javac.code.Type$ClassType cannot be cast to javax.lang.model.type.ArrayType

    EDIT: Seems like it's because of The Transformer class, when I remove it and the list field, it compile successfully.

    bug 
    opened by vincent-paing 3
  • question for SQLITE_SEQUENCE

    question for SQLITE_SEQUENCE

    how can i reset the SQLITE_SEQUENCE with sqlite magic. do sqlite magic have a way to run or exec a query like that db.execSQL("DELETE FROM sqlite_sequence WHERE name= TABLE_NAME");

    opened by IvanGarza07 3
  • Error on using with AutoValue and auto increment Id

    Error on using with AutoValue and auto increment Id

    Current my entity model has the following fields, with

    @Table(value = "address") @AutoValue @AutoGson public abstract class AddressNew {
    
        @Id public abstract long _id();
    
        public abstract String address1();
    
        //create function here
    
        @AutoValue.Builder public abstract static class Builder {
    
            public abstract Builder _id(long _id);
    
            public abstract Builder address1(String address1);
        }
    }
    

    In the generated Dao, it would call the builder constructor that doesn't exist. particularly here

    public final class SqliteMagic_AddressNew_Dao {
      public static AddressNew setId(AddressNew entity, long id) {
        return new AutoValue_AddressNew.Builder(entity)._id(id).build();
      }
    //...
    }
    
    opened by vincent-paing 2
  • database operation builder methods issue

    database operation builder methods issue

    Hi, trying out your library's examples, I cannot do a simple insert because apparently the insert method is not found in the Book class:

    @Table(persistAll = true)
    @AutoValue
    public abstract class Book
    
    Book book = new Book(77, "Bar", author);
    
    Single<Long> insert = book
        .insert()
        .observe();
    

    How can I debug why the database operation builder methods are not "automagically" generated during compile time?

    opened by abusuioc 2
  • UpdateBuilder does not work when passing value directly

    UpdateBuilder does not work when passing value directly

    Here's the reproducible code

    @Table(persistAll = true)
    public class Entity {
    
      @Id(autoIncrement = true) public Long id;
    
      public Boolean isSomething;
    }
    

    And updating isSomething column with following code

     Update.table(EntityTable.ENTITY)
            .set(EntityTable.ENTITY.IS_SOMETHING, true)
            .execute();
    

    This should translate to

    UPDATE TABLE entity SET isSomething = true
    

    However, the code does not compile because it cannot resolve method, since it does not know the method where you pass the value instead of Column..etc.

    image

    Tested on version 0.23.1

    opened by vincent-paing 1
  • Feature Request : Separate RxJava artifact

    Feature Request : Separate RxJava artifact

    In the project I'm currently working on, There's no need for me to use rxjava. I think it's better RxJava support is separated as another artifact since I don't want to bloat the app and increase app size.

    opened by vincent-paing 1
  • Update sample

    Update sample

    The sample is still using the old initialization method, it need to use the new builder pattern

    https://github.com/SiimKinks/sqlitemagic/blob/406ffb01959bfd8e3b8449053f8198e9afc2a6df/sqlitemagic-sample/app/src/main/java/com/siimkinks/sqlitemagic/sample/SampleApp.java#L11

    opened by vincent-paing 1
  • Build fails with rx java class not found

    Build fails with rx java class not found

    I can't seem to run the app because the generated class imported classes from rxjava. Even after adding the rxjava to my gradle compilation, it still fails to run. I think the rxajva implementation should be able to opt-in instead of just forcing it.

    opened by vincent-paing 1
  • please help me

    please help me

    untitled

    apply plugin: 'com.android.application' apply plugin: 'com.siimkinks.sqlitemagic'

    buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.3.2' classpath 'com.siimkinks.sqlitemagic:sqlitemagic-plugin:0.12.0' } }

    android { compileSdkVersion 25 buildToolsVersion "26.0.0" defaultConfig { applicationId "ms.nakon.foozool.app1" minSdkVersion 16 targetSdkVersion 22 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" buildConfigField "int", "DB_VERSION", "1" // Optional (defaults to "database.db") buildConfigField "String", "DB_NAME", '"sample.db"' } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } configurations.all { resolutionStrategy.eachDependency { DependencyResolveDetails details -> def requested = details.requested if (requested.group == 'com.android.support') { if (!requested.name.startsWith("multidex")) { details.useVersion '25.3.1' } } } } dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.3.1' testCompile 'junit:junit:4.12' compile 'com.android.support.constraint:constraint-layout:1.0.2' compile 'com.github.florent37:materialviewpager:1.2.1' //dependencies compile 'com.flaviofaria:kenburnsview:1.0.7' compile 'com.jpardogo.materialtabstrip:library:1.1.0' compile 'com.github.bumptech.glide:glide:3.7.0' compile 'com.jakewharton:butterknife:8.1.0' annotationProcessor 'com.jakewharton:butterknife-compiler:8.1.0' compile 'com.android.support:cardview-v7:+'

    }

    opened by msadeghifard1989 1
  • Publish to Maven Central instead of jcenter

    Publish to Maven Central instead of jcenter

    jcenter has been soft-sunsetted and most Android projects are either in the process of migrating off jcenter or have already done so. It looks like there are no sqlitemagic artifacts in maven central yet?

    https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/

    opened by madisp 1
  • Road to 1.0.0

    Road to 1.0.0

    List of features planned before releasing version 1.0.0. Feel free to propose features, changes, implementation details, APIs, etc.

    • [x] Support for multi module builds where database models are located across modules
    • [x] Ability to run raw SQL (fixes #4)
    • [x] Full conflict algorithm support
    • [x] Support object(s) update/persist operations with custom WHERE clause by unique column
    • [x] Support updating nullable columns with null values in update builder
    • [x] Support multiple object transformers in one class
    • [x] Build on top of the Android architecture components Sqlite support library
    • [x] Indices support
    • [x] Automatic migration scripts generator for debug builds
    • [x] Support for downgrading database
    • [x] Change Query#run return type from Observable to Maybe
    • [x] Change defaults to meet most used setups
    • [x] Support views in kotlin
    • [x] Support for cross-module object transformers
    • [x] Migration scripts generator gradle task for release builds
    • [x] Support for compound operators https://www.sqlite.org/syntax/compound-operator.html
    • [ ] Support embedded columns
    • [ ] Improve wiki with kotlin specific documentation
    1.0.0 
    opened by SiimKinks 0
AndroidQuery is an Android ORM for SQLite and ContentProvider which focuses on easy of use and performances thanks to annotation processing and code generation

WARNING: now that Room is out, I no longer maintain that library. If you need a library to easy access to default android ContentProvider, I would may

Frédéric Julian 19 Dec 11, 2021
An Android library that makes developers use SQLite database extremely easy.

LitePal for Android 中文文档 LitePal is an open source Android library that allows developers to use SQLite database extremely easy. You can finish most o

Lin Guo 7.9k Dec 31, 2022
SquiDB is a SQLite database library for Android and iOS

Most ongoing development is currently taking place on the dev_4.0 branch. Click here to see the latest changes and try out the 4.0 beta. Introducing S

Yahoo 1.3k Dec 26, 2022
android 数据库框架,sqlite database

DBExecutor 主要的功能 1.使用了读写锁,支持多线程操作数据。 2.支持事务 3.支持ORM 4.缓存Sql,缓存表结构 这个类库主要用于android 数据库操作。 始终围绕着一个类对应一个表的概念。 只要创建一个实体类,就不用当心它怎么存储在数据库中,不用重新写增删改查的代码。基本的功

null 77 May 31, 2021
LiteOrm is a fast, small, powerful ORM framework for Android. LiteOrm makes you do CRUD operarions on SQLite database with a sigle line of code efficiently.

#LiteOrm:Android高性能数据库框架 A fast, small, powerful ORM framework for Android. LiteOrm makes you do CRUD operarions on SQLite database with a sigle line

马天宇 1.5k Nov 19, 2022
An Android library that makes developers use SQLite database extremely easy.

LitePal for Android 中文文档 LitePal is an open source Android library that allows developers to use SQLite database extremely easy. You can finish most o

Lin Guo 7.9k Jan 4, 2023
Realm is a mobile database: a replacement for SQLite & ORMs

Realm is a mobile database that runs directly inside phones, tablets or wearables. This repository holds the source code for the Java version of Realm

Realm 11.4k Jan 2, 2023
A blazing fast, powerful, and very simple ORM android database library that writes database code for you.

README DBFlow is fast, efficient, and feature-rich Kotlin database library built on SQLite for Android. DBFlow utilizes annotation processing to gener

Andrew Grosner 4.9k Dec 30, 2022
A blazing fast, powerful, and very simple ORM android database library that writes database code for you.

README DBFlow is fast, efficient, and feature-rich Kotlin database library built on SQLite for Android. DBFlow utilizes annotation processing to gener

Andrew Grosner 4.9k Dec 30, 2022
Active record style SQLite persistence for Android

ActiveAndroid ActiveAndroid is an active record style ORM (object relational mapper). What does that mean exactly? Well, ActiveAndroid allows you to s

Michael Pardo 4.7k Dec 29, 2022
greenDAO is a light & fast ORM solution for Android that maps objects to SQLite databases.

Check out ObjectBox Check out our new mobile database ObjectBox (GitHub repo). ObjectBox is a superfast object-oriented database with strong relation

Markus Junginger 12.6k Jan 3, 2023
Active record style SQLite persistence for Android

ActiveAndroid ActiveAndroid is an active record style ORM (object relational mapper). What does that mean exactly? Well, ActiveAndroid allows you to s

Michael Pardo 4.7k Dec 29, 2022
Android SQLite API based on SQLCipher

Download Source and Binaries The latest AAR binary package information can be here, the source can be found here. Compatibility SQLCipher for Android

SQLCipher 2.6k Dec 31, 2022
Extended SQLite functionality for Android

sqlite-provider A simplification of database access for Android. Description sqlite-provider implements a ContentProvider for you that allows database

Novoda 308 Nov 20, 2022
lightweight and minimalist ORM for Java/Android. works with SQLite & MySQL. (not actively maintained)

Description ORMAN is an minimalistic and lightweight ORM framework for Java which can handle your common database usage without writing SQL and strugg

Ahmet Alp Balkan 246 Nov 20, 2022
A Java/Kotlin library for Android platform, to manage bean's persistence in SQLite, SharedPreferences, JSON, XML, Properties, Yaml, CBOR.

Thanks to JetBrains for support Kripton Persistence Library project! Kripton Persistence Library Kripton is a java library, for Android platform, that

xcesco 117 Nov 11, 2022
lightweight and minimalist ORM for Java/Android. works with SQLite & MySQL. (not actively maintained)

Description ORMAN is an minimalistic and lightweight ORM framework for Java which can handle your common database usage without writing SQL and strugg

Ahmet Alp Balkan 246 Nov 20, 2022
Extended SQLite functionality for Android

sqlite-provider A simplification of database access for Android. Description sqlite-provider implements a ContentProvider for you that allows database

Novoda 308 Nov 20, 2022
Exercicio praticando o SQLite, Room e Flow

Bus Scheduler App This folder contains the source code for the Bus Scheduler app codelab. Introduction The Bus Scheduler app displays a list of bus st

Lucas Caetano 0 Nov 26, 2021