Android ORM Framework: Detailed Explanation of GreenDao Use (Advanced)

foreword

In  Android ORM Framework: GreenDao Detailed Explanation (Basic)  , we learned about the basic use of GreenDao. In this article, we will explain the use of GreenDao in depth.

1. Complex table structure

a, use @ToOne to establish a one-to-one (1:1) relationship

@Entity
public class Order {
    @Id 
    private Long id;

    private long customerId;

    @ToOne(joinProperty = "customerId")
    private Customer customer;
}

@Entity
public class Customer {
    @Id 
    private Long id;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

b, use @ToMany to establish a one-to-many (1:N) relationship

@Entity
public class Customer {
    @Id 
    private Long id;

    @ToMany(referencedJoinProperty = "customerId")
    @OrderBy("date ASC")
    private List<Order> orders;
}

@Entity
public class Order {
    @Id private Long id;
    private Date date;
    private long customerId;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

c, use @JoinEntity to establish a many-to-many (N:M) relationship

@Entity
public class Product {
    @Id private Long id;

    @ToMany
    @JoinEntity(
            entity = JoinProductsWithOrders.class,
            sourceProperty = "productId",
            targetProperty = "orderId"
    )
    private List<Order> ordersWithThisProduct;
}

@Entity
public class JoinProductsWithOrders {
    @Id private Long id;
    private Long productId;
    private Long orderId;
}

@Entity
public class Order {
    @Id private Long id;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

Second, the custom type

1. The types supported by GreenDao by default are:

boolean, Boolean
int, Integer
short, Short
long, Long
float, Float
double, Double
byte, Byte
byte[]
String
Date
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2. Convert the data type through the @Convert annotation

For example: convert enum type to integer

@Entity
public class User {
    @Id
    private Long id;

    @Convert(converter = RoleConverter.class, columnType = Integer.class)
    private Role role;

    public enum Role {
        DEFAULT(0), AUTHOR(1), ADMIN(2);

        final int id;

        Role(int id) {
            this.id = id;
        }
    }

    public static class RoleConverter implements PropertyConverter<Role, Integer> {
        @Override
        public Role convertToEntityProperty(Integer databaseValue) {
            if (databaseValue == null) {
                return null;
            }
            for (Role role : Role.values()) {
                if (role.id == databaseValue) {
                    return role;
                }
            }
            return Role.DEFAULT;
        }

        @Override
        public Integer convertToDatabaseValue(Role entityProperty) {
            return entityProperty == null ? null : entityProperty.id;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

3. Complex query

a, conditional query

method one:

List<User> joes = userDao.queryRaw("where AGE>?","10");//查询年龄大于10的用户
  • 1

Method Two:

List<User> joes = userDao.queryBuilder().where(UserDao.Properties.Age.gt("10")).list();
  • 1

b, sort

// order by last name
queryBuilder.orderAsc(Properties.LastName);

// in reverse
queryBuilder.orderDesc(Properties.LastName);

// order by last name and year of birth
queryBuilder.orderAsc(Properties.LastName).orderDesc(Properties.YearOfBirth);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

c, pagination

limit(int) :  Limit the number of results returned by the query. 
offset(int):  set the starting position

// 从第二条记录开始查询5条记录
List<User> list = userDao.queryBuilder()
                .offset(2)
                .limit(5)
                .list();
  • 1
  • 2
  • 3
  • 4
  • 5

d, lazy loading

LazyList<User> lazyList = userDao.queryBuilder().listLazy();

for (User u:lazyList) {
      Log.i(TAG, "用户名:"+u.getName());
}

lazyList.close();   //不再使用时必须关闭,否则会导致数据库游标未关闭,从而导致内存泄漏
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

LazyList is a collection class implemented by GreenDao and implements the List interface. Therefore, you can directly use LazyList as a List.

public class LazyList<E> implements List<E>, Closeable {
//省略了具体实现
}
  • 1
  • 2
  • 3

Note : LazyList must be closed with the close() method when it is no longer in use, otherwise it will cause memory leaks.

lazyList.close();
  • 1

e, Troubleshooting

Many times we can't query the results we expect when querying. At this time, we can print the SQL log by modifying the two static member variables of QueryBuilder to facilitate troubleshooting.

QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;
  • 1
  • 2

f, multi-table joint query

QueryBuilder<User> queryBuilder = userDao.queryBuilder();

queryBuilder.join(Address.class, AddressDao.Properties.userId)
  .where(AddressDao.Properties.Street.eq("Sesame Street"));

List<User> users = queryBuilder.list();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Fourth, obfuscated configuration

### greenDAO 3
-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {
public static java.lang.String TABLENAME;
}
-keep class **$Properties

# If you do not use SQLCipher:
-dontwarn org.greenrobot.greendao.database.**
# If you do not use RxJava:
-dontwarn rx.**

### greenDAO 2
-keepclassmembers class * extends de.greenrobot.dao.AbstractDao {
public static java.lang.String TABLENAME;
}
-keep class **$Properties
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

5. Database encryption

greenDAO supports  SQLCipher  direct binding.

a, import dependencies:

compile 'net.zetetic:android-database-sqlcipher:3.5.7@aar'
  • 1

b, initialize the encrypted database

DevOpenHelper helper = new DevOpenHelper(this, "notes-db-encrypted.db");
Database db = helper.getEncryptedWritableDb("<your-secret-password>");
daoSession = new DaoMaster(db).newSession();
  • 1
  • 2
  • 3

c、其他操作和未加密一样(是不是特别简单)

当然,如果你不是使用 GreenDao 数据库,同样可以使用 SQLCipher 加密保护我们的数据,详细请参考SQLCipher for Android

六,整合 RxJava

Rxjava 的火爆程度已经是如日中天了,GreenDao 对当然也是对提供对 Rxjava 的支持。(比较失望的是目前 GreedDao 仅支持 Rxjava 1,不支持 Rxjava 2)

1,引入 Rxjava 依赖

compile 'io.reactivex:rxandroid:1.2.1'
compile 'io.reactivex:rxjava:1.2.9'
  • 1
  • 2

3,初始化 GreedDao 配置

public class App extends Application {
    /**
     * 加密标识符
     */
    public static final boolean ENCRYPTED = true;

    private DaoSession daoSession;

    @Override
    public void onCreate() {
        super.onCreate();

        DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this,ENCRYPTED ? "notes-db-encrypted" : "notes-db");
        Database db = ENCRYPTED ? helper.getEncryptedWritableDb("super-secret") : helper.getWritableDb();
        daoSession = new DaoMaster(db).newSession();
    }

    public DaoSession getDaoSession() {
        return daoSession;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

3, 获取 RxDao

 User user = new User();
 user.setUserId(10);
 user.setName("小红");
 user.setAge(18);

 DaoSession daoSession = ((MyApp) getApplication()).getDaoSession();
 RxDao<User, Long> userDao = daoSession.getUserDao().rx();

 userDao.insert(user)
         .observeOn(AndroidSchedulers.mainThread())
         .subscribe(new Action1<User>() {
             @Override
             public void call(User user) {
                 Log.i(TAG, "保存成功 ");
             }
         });

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325579308&siteId=291194637