Android ORMLite框架入门级介绍

以前使用数据库都是使用Android官方推荐的SQLiteOpenHelper,用过的都知道,比较难用。一直想找一个比较好用的数据库框架,直到我遇到了ORMLite框架~

这里写了一个小Demo抛砖引玉,github项目地址

先来一段复制粘贴的简介: ORM(全称Object Relation Mapping)叫做对象关系映射,是一种程序设计技术,用于实现面向对象编程语言中不同类型系统的数据之间的转换。

再来一段复制粘贴的优缺点:

先说说优点:
轻量级
使用简单,易上手
封装完善
文档全面

缺点:
基于反射,效率较低
缺少中文翻译文档

官方网站(说实话是晦涩难懂):官方网站

可以不看上面这些非常官方的话用咱们通俗易懂的话来讲,它的工作过程是这样子的

它可以直接将Bean文件转换成数据库中的表,Bean中的属性就是表的列,它将繁琐的数据库操作封装成一个Dao类,使用Dao类和Bean可以直接对数据库进行操作,参数什么的非常简单,大多数的方法参数只有一个Bean对象。

好了,开始介绍ORMLite框架

一、配置jar

我还没有找到在Gradle中直接compile的方法,那么就要下载jar文件了~
官网jar文件下载地址,在这里下载两个jar文件:ormlite-android-5.0.jar和ormlite-core-5.0.jar,版本可能有出入,毕竟官网在更新嘛~
下载好了之后可以配置到我们的工程中了,如果你还不会配置jar文件(⊙o⊙)…百度吧

二、创建Bean类

既然上面的工作过程说到了Bean,那么我们就不得不写一个Bean类了~

这里先上一些我写的Bean的代码代码下面进行解释

package com.myar.www.myar.beans;

import com.j256.ormlite.field.DataType;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;

/**
 * Created by MQL on 2017/8/18.
 */

@DatabaseTable
public class User {
    @DatabaseField(generatedId = true)
    private int id;

    @DatabaseField(dataType = DataType.STRING)
    private String name;

    @DatabaseField
    private String desc;

    public User(){

    }

    public User(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}   

在这里我们看到两个注解(什么!?你连注解都不明白?看这篇文章吧):

@DatabaseTable

这个注解就标识了User这个Bean类为一张数据库表,默认以类名为表名,如果想自定义表名也可以,那么需要这样写:

@DatabaseTable(tableName = "表名")

这样就更改了默认表名

第二个注解:

@DatabaseField

这个注解用来标识这个属性为表中的列,当然,这个注解也可以加参数:

columnName  自定义字段名,默认为Bean类属性名

dataType 数据类型,如果没有这个参数,会根据属性类型自动转化,不过推荐写上,万一自动转化出了错误呢!
 
defaultValue 字段默认值
 
canBeNull 可否为空
 
id 主键
 
generatedId 自增主键,如果为true,则该主键自动生成并且递增
 
foreign 外联
 
unique 唯一

这里着重看一下dataType参数吧:
常用数据类型:

STRING(StringType.getSingleton()),

BOOLEAN(BooleanType.getSingleton()),

DATE(DateType.getSingleton()),

DATE_LONG(DateLongType.getSingleton()),

CHAR(CharType.getSingleton()),

BYTE(ByteType.getSingleton()),

SHORT(ShortType.getSingleton()),

INTEGER(IntType.getSingleton()),

LONG(LongType.getSingleton()),

FLOAT(FloatType.getSingleton()),

DOUBLE(DoubleType.getSingleton()),

SERIALIZABLE(SerializableType.getSingleton()),

TIME_STAMP(TimeStampType.getSingleton())

这样Bean类就创建完了,等着被使用就行了~

二、继承OrmLiteSqliteOpenHelper,创建数据库帮助类

就像使用SQLiteOpenHelper框架一样,使用ORMLite框架也需要一个帮助类,这个帮助类继承OrmLiteSqliteOpenHelper,其实也是间接的继承了SQLiteOpenHelper,只是被封装的更好用了。

还是老规矩,先看下代码,代码下面进行解释:

package com.myar.www.myar.databases;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import com.myar.www.myar.beans.Card;
import com.myar.www.myar.beans.User;

import java.sql.SQLException;

/**
 *
 * Created by MQL on 2017/8/18.
 */

public class DatabaseHelp extends OrmLiteSqliteOpenHelper {

private static final String DB_NAME="sqlite-test.db";

private static final int DB_VERSION=1;

private static DatabaseHelp instance;

private DatabaseHelp(Context context){
    super(context,DB_NAME,null,DB_VERSION);
}

public static synchronized DatabaseHelp getHelp(Context context){
    if(instance == null){
        synchronized (DatabaseHelp.class){
            if(instance == null){
                instance = new DatabaseHelp(context);
            }
        }
    }
    return instance;
}

@Override
public void close() {
    super.close();
    userDao = null;
    cardDao = null;
}

@Override
public void onCreate(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource) {
    try{
        TableUtils.createTable(connectionSource,User.class);
        TableUtils.createTable(connectionSource, Card.class);
    }catch (SQLException e){
        e.printStackTrace();
    }
}

@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource, int i, int i1) {
    try {
        TableUtils.dropTable(connectionSource,User.class,true);
        TableUtils.dropTable(connectionSource,Card.class,true);
        onCreate(sqLiteDatabase, connectionSource);
    } catch (SQLException e) {
        e.printStackTrace();
    }
}


private Dao<User, Integer> userDao;

public Dao<User, Integer> getUserDao() throws SQLException{
    if(userDao == null){
        userDao = getDao(User.class);
    }
    return userDao;
}

private Dao<Card, Integer> cardDao;

public Dao<Card, Integer> getCardDao() throws SQLException{
    if(cardDao == null){
        cardDao = getDao(Card.class);
    }
    return cardDao;
}
}

咱们从哪里说起呢~
(1)先说说构造方法吧~
把上面的构造方法有关的代码找出来:

private static final String DB_NAME="sqlite-test.db";

private static final int DB_VERSION=1;

private static DatabaseHelp instance;

private DatabaseHelp(Context context){
    super(context,DB_NAME,null,DB_VERSION);
}

public static synchronized DatabaseHelp getHelp(Context context){
    if(instance == null){
        synchronized (DatabaseHelp.class){
            if(instance == null){
                instance = new DatabaseHelp(context);
            }
        }
    }
    return instance;
}

这里我们使用了单例模式(什么!单例模式不明白?先百度一下吧)来进行创建数据库对象,至于为什么要使用单例模式创建数据库对象呢,这里简单说一下,这牵扯到多线程访问数据库时如果是多个数据库对象,那么就会引起线程不安全,因为SQLiteDatabase对象是线程不安全的,也就是说它没有线程锁,而DatabaseHelp对象就是线程安全的,如果多个线程使用同一个DatabaseHelp对象访问数据库,就不会出现线程不安全的问题,所以使用单例模式创建数据库对象,使整个应用都使用同一个数据库对象访问数据库~

我先定义了两个常量,一个是数据库名,一个是数据库版本,然后是一个全局变量,这个全局变量就是我们的数据库对象了,接下来我们写了构造方法,这个构造方法是一个private方法,这样就不能使用new来创建数据库对象,然后我又开启了一个获取数据库对象的接口方法getHelp,这个方法是全局方法,在任何地方都可以调用,里面就是单例模式中的懒汉模式两次判定创建数据库对象,这个就不说了,单例模式里面的知识。

(2)然后我们需要重写两个重要的方法:onCreate和onUpgrade,一个用于创建数据库表,一个用于更新数据库表。
把有关代码找出来:

 @Override
public void onCreate(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource) {
    try{
        TableUtils.createTable(connectionSource,User.class);
        TableUtils.createTable(connectionSource, Card.class);
    }catch (SQLException e){
        e.printStackTrace();
    }
}

@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource, int i, int i1) {
    try {
        TableUtils.dropTable(connectionSource,User.class,true);
        TableUtils.dropTable(connectionSource,Card.class,true);
        onCreate(sqLiteDatabase, connectionSource);
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

先说说onCreate方法,可以看到方法体中使用了TableUtils类的createTable方法创建了数据库表,这里我两次调用也就是创建了两张表,一张User,一张Card。TableUtils类是ORMLite框架提供的类,它专门用于对表的操作,除了createtable方法之外还有其他方法,这里再说两个最常用的方法

dropTable //删除表

clearTable //清空表

再说说onUpgrade方法,它的方法体中先将表删除,再重新创建,这样就完成了更新表的目的,很简单~

(3)另外一个要说的就是数据库帮助类需要向外提供Dao类对象来对数据库操作

在开头的工作流程中也说了,ORMLite需要Dao类对数据库进行操作,那么我们先把有关代码找出来~

private Dao<User, Integer> userDao;

public Dao<User, Integer> getUserDao() throws SQLException{
    if(userDao == null){
        userDao = getDao(User.class);
    }
    return userDao;
}

private Dao<Card, Integer> cardDao;

public Dao<Card, Integer> getCardDao() throws SQLException{
    if(cardDao == null){
        cardDao = getDao(Card.class);
    }
    return cardDao;
}

这是两个获取Dao对象的方法,一张表对应一个Dao对象,我们可以看到这个Dao类还有两个泛型,这两个泛型的含义是这样的:

第一个泛型是Dao类操作的类

第二个泛型是被操作表的主键类型

这样就非常明白了吧~

这样我们通过数据库帮助类对象调用getUserdao()就可以获取Dao对象了

三、封装Dao对象,使Dao更好用!

还是老规矩,先看看代码:

package com.myar.www.myar.databases;

import android.content.Context;

import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.QueryBuilder;
import com.myar.www.myar.beans.User;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * Created by MQL on 2017/8/18.
 */

public class UserDao {
    private Dao<User, Integer> userDao;

    private DatabaseHelp dbHelp;

    public UserDao(Context context){
        dbHelp = DatabaseHelp.getHelp(context);
        try {
            userDao = dbHelp.getUserDao();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void add(User user) {
        try {
            userDao.create(user);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void delete(User user) {
        try {
            userDao.delete(user);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void updata(User user) {
        try {
            userDao.update(user);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    public User queryForId(int id) {
        User user = null;
        try {
            user = userDao.queryForId(id);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return user;
    }

    public List<User> queryForAll() {
        List<User> users = new ArrayList<>();
        try {
            users = userDao.queryForAll();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return users;
    }
}

这里我只封装了简单的5个操作,增删改查和一个查询全部
(1)先说说构造方法吧~
找出有关代码:

    private Dao<User, Integer> userDao;

    private DatabaseHelp dbHelp;

    public UserDao(Context context){
        dbHelp = DatabaseHelp.getHelp(context);
        try {
            userDao = dbHelp.getUserDao();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

这里定义了两个对象,一个DatabaseHelp对象,一个Dao< User, Integer >对象,我们在构造方法里先获取了DatabaseHelp对象,注意这里是使用的刚刚开启的获取DatabaseHelp对象的全局接口方法,然后通过DatabaseHelp对象获取Dao对象。
我们对数据库进行操作都是使用Dao对象的一系列方法进行的。

(2)再来看看操作方法:
还是先找出代码,这里仅举一例,其他的都一样~

public void add(User user) {
        try {
            userDao.create(user);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

这里仅以添加为例子,其他的都是一样的,这里我们想当与是对Dao类的create方法进行了封装,我们可以看到,仅仅传入一个User类对象就可以实现往数据库中添加数据,真是简单到爆!

关于对数据的增删改查当然不只有代码上的几个方法,这里再列出几个方法:

添加数据:

int create(T t) throws SQLException; //单个添加数据

int create(Collection<T> var1) throws SQLException; //以集合的形式批量添加数据

T createIfNotExists(T t) throws SQLException; //如果数据不重复,就添加数据

删除数据:

int delete(T t) throws SQLException; //单个删除数据

int deleteById(Intenger id) throws SQLException; //匹配主键删除数据

int delete(Collection<T> var1) throws SQLException; //以集合的形式批量删除数据

int deleteIds(Collection<Intenger>  ids) throws SQLException; //以集合的形式批量匹配主键删除数据

更新数据:

nt update(T var1) throws SQLException; //单个更新数据

int updateId(T var1, ID var2) throws SQLException; //匹配主键更新数据

查询数据:

T queryForId(ID var1) throws SQLException; //匹配主键查询数据

List<T> queryForAll() throws SQLException; //查询全部数据

四、另外,如果对于查询有比较高的需求怎么办?
下一篇博客:Android ORMLite框架 复杂查询

MQL于2017年8月19日完成本文。

    原文作者:MQLX
    原文地址: https://www.jianshu.com/p/856807b72333
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞