Giter Club home page Giter Club logo

freezer's Introduction

Freezer

Android Arsenal CircleCI

Android app on Google Play

A simple & fluent Android ORM, how can it be easier ? And it's compatible with RxJava2 !

UserEntityManager userEntityManager = new UserEntityManager();

userEntityManager.add(new User("Florent", 6));
userEntityManager.add(new User("Florian", 3));
userEntityManager.add(new User("Bastien", 3));

List<User> allUsers = userEntityManager.select()
                             .name().startsWith("Flo")
                             .asList();

userEntityManager.select()
       .age().equals(3)
       .asObservable()

       .subscribeOn(Schedulers.newThread())
       .observeOn(AndroidSchedulers.mainThread())
       .subscribe(users ->
          //display the users
       );

First, initialize !

Don't forget to initialise Freezer in your application:

public class MyApplication extends Application {

    @Override public void onCreate() {
        super.onCreate();
        Freezer.onCreate(this);
    }

}

Second, annotate your models

Use Annotations to mark classes to be persisted:

@Model
public class User {
    int age;
    String name;
    Cat cat;
    List<Cat> pets;
}
@Model
public class Cat {
    @Id long id;
    String name;
}

Now, play with the managers !

Persist datas

Persist your data easily:

UserEntityManager userEntityManager = new UserEntityManager();

User user = ... // Create a new object
userEntityManager.add(user);

Querying

Freezer query engine uses a fluent interface to construct multi-clause queries.

Simple

To find all users:

List<User> allUsers = userEntityManager.select()
                             .asList();

To find the first user who is 3 years old:

User user3 = userEntityManager.select()
                    .age().equalsTo(3)
                    .first();

Complex

To find all users

  • with name "Florent"
  • or who own a pet with named "Java"

you would write:

List<User> allUsers = userEntityManager.select()
                                .name().equalsTo("Florent")
                             .or()
                                .cat(CatEntityManager.where().name().equalsTo("Java"))
                             .or()
                                .pets(CatEntityManager.where().name().equalsTo("Sasha"))
                             .asList();

Selectors

//strings
     .name().equalsTo("florent")
     .name().notEqualsTo("kevin")
     .name().contains("flo")
     .name().in("flo","alex","logan")
//numbers
     .age().equalsTo(10)
     .age().notEqualsTo(30)
     .age().greatherThan(5)
     .age().between(10,20)
     .age().in(10,13,16)
//booleans
     .hacker().equalsTo(true)
     .hacker().isTrue()
     .hacker().isFalse()
//dates
     .myDate().equalsTo(OTHER_DATE)
     .myDate().notEqualsTo(OTHER_DATE)
     .myDate().before(OTHER_DATE)
     .myDate().after(OTHER_DATE)

Aggregation

The QueryBuilder offers various aggregation methods:

float agesSum      = userEntityManager.select().sum(UserColumns.age);
float agesAverage  = userEntityManager.select().average(UserColumns.age);
float ageMin       = userEntityManager.select().min(UserColumns.age);
float ageMax       = userEntityManager.select().max(UserColumns.age);
int count          = userEntityManager.select().count();

Limit

The QueryBuilder offers a limitation method, for example, getting 10 users, starting from the 5th:

List<User> someUsers = userEntityManager.select()
                                .limit(5, 10) //start, count
                                .asList();

Asynchronous

Freezer offers various asynchronous methods:

Add / Delete / Update

userEntityManager
                .addAsync(users)
                .async(new SimpleCallback<List<User>>() {
                    @Override
                    public void onSuccess(List<User> data) {

                    }
                });

Querying

userEntityManager
                .select()
                ...
                .async(new SimpleCallback<List<User>>() {
                    @Override
                    public void onSuccess(List<User> data) {

                    }
                });

Observables

With RxJava

userEntityManager
                .select()
                ...
                .asObservable()
                ... //rx operations
                .subscribe(new Action1<List<User>>() {
                    @Override
                    public void call(List<User> users) {
                    
                    }
                });

Entities

Freezer makes it possible, yes you can design your entities as your wish:

@Model
public class MyEntity {

    // primitives
    [ int / float / boolean / String / long / double ] field;
    
    //dates
    Date myDate;

    // arrays
    [ int[] / float[] / boolean[] / String[] / long[] / double ] array; 
    
    // collections
    [ List<Integer> / List<Float> / List<Boolean> / List<String> / List<Long> / List<Double> ] collection;
    
    // One To One
    MySecondEntity child;
    
    // One To Many
    List<MySecondEntity> childs;
}

Update

You can update a model:

user.setName("laurent");
userEntityManager.update(user);

Id

You can optionnaly set a field as an identifier:

@Model
public class MyEntity {
    @Id long id;
}

The identifier must be a long

Ignore

You can ignore a field:

@Model
public class MyEntity {
    @Ignore
    int field;    
}

Logging

You can log all SQL queries from entities managers:

userEntityManager.logQueries((query, datas) -> Log.d(TAG, query) }

Migration

To handle schema migration, just add @Migration(newVersion) in a static method, then describe the modifications:

public class DatabaseMigration {

    @Migration(2)
    public static void migrateTo2(Migrator migrator) {
        migrator.update("User")
                .removeField("age")
                .renameTo("Man");
    }

    @Migration(3)
    public static void migrateTo3(Migrator migrator) {
        migrator.update("Man")
                .addField("birth", ColumnType.Primitive.Int);
    }
    
    @Migration(4)
    public static void migrateTo4(Migrator migrator) {
        migrator.addTable(migrator.createModel("Woman")
                .field("name", ColumnType.Primitive.String)
                .build());
    }
}

Migration isn't yet capable of:

  • changing type of field
  • adding/modifying One To One
  • adding/modifying One To Many
  • handling collections/arrays

Download

Android app on Google Play

Buy Me a Coffee at ko-fi.com

Download

buildscript {
  dependencies {
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
  }
}

apply plugin: 'com.neenbedankt.android-apt'

dependencies {
  compile 'fr.xebia.android.freezer:freezer:2.0.6'
  provided 'fr.xebia.android.freezer:freezer-annotations:2.0.6'
  apt 'fr.xebia.android.freezer:freezer-compiler:2.0.6'
}

Changelog

1.0.1

Introduced Migration Engine.

1.0.2

  • Support long & double
  • Support arrays
  • Improved QueryBuilder
  • Refactored cursors helpers

1.0.3

  • Support dates
  • Added unit tests
  • Fixed one to many

1.0.4

  • Added @Id & @Ignore

1.0.5

  • Model update

2.0.0

  • Async API
  • Support Observables
  • Added @DatabaseName

2.0.1

  • Limit

2.0.2

  • Added query.in(...values...)

2.0.3

  • Freezer.onCreate is no longer dynamic

2.0.5

  • Improved performace for batch add & update (thanks to graphee-gabriel)

2.0.6

  • Add or update object if same @Id on add, addAll`

2.1.0

  • Added RxJava2 support

A project initiated by Xebia

This project was first developed by Xebia and has been open-sourced since. We will continue working on it. We encourage the community to contribute to the project by opening tickets and/or pull requests.

logo xebia

Android app on Google Play Android app on Google Play

License

Copyright 2015 Xebia, Inc.

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.

freezer's People

Contributors

arnaudpiroelle avatar bryant1410 avatar florent37 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

freezer's Issues

Duplicates within relations

Duplicate entries of relations are created, when the parent entity is being updated.

Scenario: The app fetches data from an API & stores it in a table, this is the model:

Tour {
List(Place) places;
…
}

Step 1: App fetches data, like fetchAllTours()
Step 2: A tour is added on API side, i.e. all existing tours stay the same --> fetchAllTours()

All the existing tours get updated in the DB now, but each time a new row in the pivot table ("TOUR_PLACE") is being created. Resulting in duplicates: Getting one of the already existing Tours from the DB will now have each place twice.

List<Long> creates helper classes with Integer

Reproduce:

Create a POJO, like so:

@model
public class Place {
public String name;
@id
public long id;
public List numbers;
}

Then build the project --> Android Studio will give you an error:

incompatible types: List cannot be converted to List

in PlaceCursorHelper

relationship to same object

i've this DB
############
Condiments
id
name
priceToRemove
priceToAdd
############

############
Category
id
name
############

############
Products
id
name
price
condiments (list)
category (object)
############

so I create a category > Pizza
than create another category > Panzerotti

than create condiment > mozzarella
than another condiment > pomodoro

than create product > Margherita with category "pizza" and condiments "mozzarella, pomodoro"
than create another product > Panzerotto fritto with category "panzerotto" and condiments "pomodoro"

I get this error

attempt to re-open an already-closed object: SQLiteDatabase: /data/data/it.croccio.gesty/databases/database.db

@florent37

Update or Create

Is there any feature like create if the data not exists or update

how to update object inner object

Hi! I've this classes

public class Condiment {

long priority;
CondimentCategory category;
String name;
float priceToAdd;
float priceToRemove;

}

and class CondimentCategory.

if I save a condiment it's ok. Than I update condiment object and change CondimentCategory, but after update condimentCategory not changed.

How can I update all?

Migration Not fire

migration not fire i wrote the code but it did not work ?

@DatabaseName("database")
public class DatabaseMigration {

@Migration(1)
public static void migrateTo1(Migrator migrator) {
    migrator.update("TIME")
            .addField("isBusy", ColumnType.Primitive.Boolean);
}

}

and it say's the class never used

Unable to access classes

Added and compiled the dependencies successfully but i am unable to access the classes in my application,
Example: I cannot access Freezer.onCreate(this);

Freezer close database after every operation

Which may cause "java.lang.IllegalStateException: attempt to re-open an already-closed object." or "java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed."

Default Value

Is i able to set default value like createdDate = current time

Select distinct on Single Column

How can i run
select distinct MESSAGEMODEL.fromUser from MESSAGEMODEL

i am using
messageModelEntityManager.select().fields(MessageModelColumns.fromUser).asList()

that gives the query
select distinct MESSAGEMODEL._id, MESSAGEMODEL.fromUser from MESSAGEMODEL

how can i make query that distinct single column

Compilation failed

I've just init a empty project and adding dependency to your library lead to :

Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
java.lang.UnsupportedClassVersionError: fr/xebia/android/freezer/annotations/Model : Unsupported major.minor version 52.0

SQLiteException: no such table after adding a new Model

I added a new Model class 'ATM' and when I start the app I get:

SQLiteException: no such table: ATM (code 1): , while compiling: INSERT OR REPLACE INTO ATM(att1,att2,att3,att4,att5) VALUES (?,?,?,?,?)

Do I actually need to run a Migration to add a table?

(That's what I plan to do as a workaround)

Can't access database in multi thread

I also accounted the same issue #17 when access database in multithread . Now I use synchronized for all db manipulations(both read and write) , so that only one thread to access db to prevent these issue. Any other good suggestion Or you can add multi thread access support in next release?

java 8 issue

Warning:Supported source version 'RELEASE_7' from annotation processor 'fr.xebia.android.freezer.Processor' less than -source '1.8'

[Doc] Wrong package name

Hello Florent,

Just to inform you that's theres is a mistake in your Readme.MD regarding package name.

The following will work (note the fr.xebia instead the com.xebia)

dependencies {
apt 'fr.xebia.android.freezer:freezer-compiler:1.0.0'
provided 'fr.xebia.android.freezer:freezer-annotations:1.0.0'
}

Have a good day !

Can't select double variable in Model

Hi !

As the title of the issue say, i created a Model :

@Model
public class FavoriteSpot {

    String name;

    double latitude;

    double longitude;

    long timestamp;

    int used;

    public FavoriteSpot(){

    }

    public FavoriteSpot(String name, LatLng latLng, long timestamp){
        this.name = name;
        latitude = latLng.latitude;
        longitude = latLng.longitude;
        this.timestamp = timestamp;
        used = 0;
    }

    @Override
    public String toString() {
        return "FavoriteSpot{" +
                "name='" + name + '\'' +
                ", latitude=" + latitude +
                ", longitude=" + longitude +
                ", timestamp=" + timestamp +
                ", used=" + used +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getLatitude() {
        return latitude;
    }

    public double getLongitude() {
        return longitude;
    }

    public long getTimestamp() {
        return timestamp;
    }

    public int getUsed() {
        return used;
    }
}

When i tried to get my Model through it's entity manager, i can not access to it's double variables (latitude and longitude), for example :

favoriteSpotEntityManager.select().latitude() -> Did not work πŸ‘Ž

but :

favoriteSpotEntityManager.select().name() -> Is working fine πŸ‘

It's probably me who didn't use correctly the library, because your change log explicitly say that you handle double value. So if you can point my error i would be glad.

create new db

is it possible to have different db and create new one every day? I save a lot of data in one day and db operation become very slow.

Cannot find Freezer and error: cannot assign a value to final variable CREATOR

I followed readme file, but i get this error

Error:(31, 35) error: cannot assign a value to final variable CREATOR
Error:(31, 46) error: incompatible types: List<Article> cannot be converted to Creator<Article>
Error:(73, 24) error: no suitable method found for insertForArticle(SQLiteDatabase,Creator<Article>,long,String)
method ArticleCursorHelper.insertForArticle(SQLiteDatabase,Article,long,String) is not applicable
(argument mismatch; Creator<Article> cannot be converted to Article)
method ArticleCursorHelper.insertForArticle(SQLiteDatabase,List<Article>,long,String) is not applicable
(argument mismatch; Creator<Article> cannot be converted to List<Article>)
Error:(88, 24) error: no suitable method found for updateForArticle(SQLiteDatabase,Creator<Article>,Long,String)
method ArticleCursorHelper.updateForArticle(SQLiteDatabase,Article,long,String) is not applicable
(argument mismatch; Creator<Article> cannot be converted to Article)
method ArticleCursorHelper.updateForArticle(SQLiteDatabase,List<Article>,long,String) is not applicable
(argument mismatch; Creator<Article> cannot be converted to List<Article>)

here Article class

`@Model
public class Article implements Parcelable {

String title;
String imageUrl;
Date date;
String content;
String description;
String author;
List<String> tags;
String comments;
String formattedDate;

public String getTitle() {
    return title;
}

public Article setTitle(String title) {
    this.title = title;
    return this;
}

public Article setImageUrl(String imageUrl) {
    this.imageUrl = imageUrl;
    return this;
}

public Date getDate() {
    return date;
}

public Article setDate(long date) {
    this.date = new Date(date);
    this.formattedDate = DateUtils.getRelativeTimeSpanString(date).toString();
    return this;
}

public String getContent() {
    return content;
}

public Article setContent(String content) {
    this.content = content;
    return this;
}

public String getAuthor() {
    return author;
}

public Article setAuthor(String author) {
    this.author = author;
    return this;
}

public String getDescription() {
    return description;
}

public Article setDescription(String description) {
    this.description = description;
    return this;
}

public List<String> getTags() {
    return tags;
}

public Article setTags(List<String> tags) {
    this.tags = tags;
    return this;
}

public String getComments() {
    return comments;
}

public Article setComments(String comments) {
    this.comments = comments;
    return this;
}

public String getFormattedDate() {
    return formattedDate;
}

public String getImageUrl() {
    return imageUrl;
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(this.title);
    dest.writeString(this.imageUrl);
    dest.writeLong(date != null ? date.getTime() : -1);
    dest.writeString(this.content);
    dest.writeString(this.description);
    dest.writeString(this.author);
    dest.writeStringList(this.tags);
    dest.writeString(this.comments);
    dest.writeString(this.formattedDate);
}

public Article() {
}

protected Article(Parcel in) {
    this.title = in.readString();
    this.imageUrl = in.readString();
    long tmpDate = in.readLong();
    this.date = tmpDate == -1 ? null : new Date(tmpDate);
    this.content = in.readString();
    this.description = in.readString();
    this.author = in.readString();
    this.tags = in.createStringArrayList();
    this.comments = in.readString();
    this.formattedDate = in.readString();
}

public static final Parcelable.Creator<Article> CREATOR = new Parcelable.Creator<Article>() {
    public Article createFromParcel(Parcel source) {
        return new Article(source);
    }

    public Article[] newArray(int size) {
        return new Article[size];
    }
};

}
`

and i cannot find Freezer class also after build

Cannot find UserEntityManager.

I know this sounds like a stupid question. I am fairly new to this architecture. I couldn't find UserEntityManager and CatEntityManager classes in the demo, that seems to be in
com.github.florent37.orm.model.CatEntityManager and
com.github.florent37.orm.model.UserEntityManager, but are not. How to resolve this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.