以前使用数据库都是使用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日完成本文。