关于Android数据库orm工具库对比的几点思考(二)

一、前言

上一篇详细解析了关于greenDao的具体用法,接下来的主角就是OrmLite,本篇博客将详细介绍ORMLite的简易用法。感兴趣的可以去官网查看,点击进入官网,它的英文全称是Object Relational Mapping,意思是对象关系映射;如果接触过Java EE开发的,一定知道Java Web开发就有一个类似的数据库映射框架——Hibernate。简单来说,就是我们定义一个实体类,利用这个框架,它可以帮我们吧这个实体映射到我们的数据库中,在Android中是SQLite,数据中的字段就是我们定义实体的成员变量。


二、OrmLite的介绍

ormlite-android
项目地址:https://github.com/j256/ormlite-android
文档介绍:http://ormlite.com/sqlite_java_android_orm.shtml

优点:

  • 轻量级
  • 使用简单,易上手
  • 封装完善
  • 文档全面

缺点:

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

三、OrmLite的使用

(一)导入jar包到项目libs文件夹下

可以通过官方发布页面下载jar包,ORMLite release page,目前最新的是5.0。在android应用中使用,我们需要下载ormlite-android-5.0.jar和ormlite-core-5.0.jar两个文件。

(二)工程使用

配置model类
User类:

// 配置该User实体类对应的表名为orm_user,如果不加tableName="orm_user"属性,则表名为类名
@DatabaseTable(tableName = "orm_user")
public class User {

    // 配置字段名为id,并设为主键
    @DatabaseField(columnName = "id", generatedId = true)
    private int id;
    // 配置字段名为name,并且该字段不能为空
    @DatabaseField(columnName = "name", canBeNull = false)
    private String name;
    // 使用本身变量名为字段名
    @DatabaseField
    private int age;
    // 使用本身变量名为字段名,并且设置默认值
    @DatabaseField(defaultValue = "这个人很懒,什么也没说")
    private String desc;
    // 一个用户对应多篇文章,eager = true表示可以进行懒加载
    // 注:这里是一对多的关系,如果是1对1,我们要用@DatabaseField注解,还要指定(foreign = true)表示是一个外键
    @ForeignCollectionField(eager = true)
    public ForeignCollection<Article> articles;

    /**
     * @return the id
     */
    public int getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(int id) {
        this.id = id;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the age
     */
    public int getAge() {
        return age;
    }

    /**
     * @param age the age to set
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * @return the desc
     */
    public String getDesc() {
        return desc;
    }

    /**
     * @param desc the desc to set
     */
    public void setDesc(String desc) {
        this.desc = desc;
    }

    /**
     * @return the articles
     */
    public ForeignCollection<Article> getArticles() {
        return articles;
    }

    /**
     * @param articles the articles to set
     */
    public void setArticles(ForeignCollection<Article> articles) {
        this.articles = articles;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return "User [id=" + id + ", name=" + name + ", age=" + age + ", desc="
                + desc + "]";
    }
}

Article类:

// 配置该Article实体类对应的表名为orm_article,如果不加tableName="orm_article"属性,则表名为类名
@DatabaseTable(tableName = "orm_article")
public class Article {

    // 配置字段名为id,并设为主键
        @DatabaseField(columnName="id",generatedId=true)
        private int id;
        // 配置字段名为name,并且该字段不能为空
        @DatabaseField(columnName="uid",canBeNull = false)
        private int uid;
        // 使用本身变量名为字段名
        @DatabaseField
        private String title;
        // 使用本身变量名为字段名
        @DatabaseField
        private String content;
        // 使用本身变量名为字段名
        @DatabaseField
        private String date;

        // 外部对象字段,并指定这个字段的对象是一个外键,外键值是这个对象的id
        @DatabaseField(foreign = true, foreignAutoRefresh = true)
        private User mUser;

        /**
         * @return the id
         */
        public int getId() {
            return id;
        }

        /**
         * @param id the id to set
         */
        public void setId(int id) {
            this.id = id;
        }

        /**
         * @return the uid
         */
        public int getUid() {
            return uid;
        }

        /**
         * @param uid the uid to set
         */
        public void setUid(int uid) {
            this.uid = uid;
        }

        /**
         * @return the title
         */
        public String getTitle() {
            return title;
        }

        /**
         * @param title the title to set
         */
        public void setTitle(String title) {
            this.title = title;
        }

        /**
         * @return the content
         */
        public String getContent() {
            return content;
        }

        /**
         * @param content the content to set
         */
        public void setContent(String content) {
            this.content = content;
        }

        /**
         * @return the date
         */
        public String getDate() {
            return date;
        }

        /**
         * @param date the date to set
         */
        public void setDate(String date) {
            this.date = date;
        }

        /**
         * @return the mUser
         */
        public User getmUser() {
            return mUser;
        }

        /**
         * @param mUser the mUser to set
         */
        public void setmUser(User mUser) {
            this.mUser = mUser;
        }

        /* (non-Javadoc)
         * @see java.lang.Object#toString()
         */
        @Override
        public String toString() {
            return "Article [id=" + id + ", uid=" + uid + ", title=" + title
                    + ", content=" + content + ", date=" + date + "]";
        }
}

@DatabaseTable 注解中,tableName 参数是可选的,也就是这个类对应的表名。如果没有特别指出,那么这个类名将默认作为表名。对于类中的每个需要存储的成员变量,都需要添加@DatabaseField注解。

@DatabaseField 常用注解:

  • columnName 指定字段名,不指定则变量名作为字段名
  • canBeNull 字段是否能被分配null值。默认是true。如果你设置成false,那么你每次在数据库中插入数据是都必须为这个字段提供值。
  • dataType 指定字段的类型
  • defaultValue 当我们在表中创建新的记录时的一个字段的默认值。默认情况下是没有这个值的
  • width 字段的宽度,主要用于字符串字段。默认是0
  • id 这个字段是否是id,默认是false。在一个class中只有一个成变量可以有这个值。id字段是一条记录的唯一标识而且是必需的,只能在generatedId和 generatedIdSequence其中选一个。
  • generatedId 字段是否自动增加。默认为false。类中的一个成员变量设置了这个值,它告诉数据库每添加一条新记录都自动增加 id。当一个有generatedid的对象被创建时使用Dao.create()方法,数据库将为记录生成一个id,它会被返回并且被create方法设置进对象。
  • generatedIdSequence 序列编号的名字,这个值在生成的时候会被使用。和generatedId相似,但是你能够指定使用的序列名称。默认是没有的。
  • foreign 指定这个字段的对象是一个外键,外键值是这个对象的id
  • persisted 指定是否持久化此变量,默认true
  • foreignAutoCreate 外键不存在时是否自动添加到外间表中
  • foreignColumnName 外键字段指定的外键表中的哪个字段

还有一个外键的相关注解,这里也写下来供参考。

@ForeignCollectionField常用注解

  • eager 表示该集合是在初始化这个对象的时候,是否讲对象取出还是在遍历的时候才取出,默认false遍历的时候才取出,size()方法也会引起遍历
  • columnName
  • orderColumnName
  • foreignFieldName

(三)创建DB Helper

创建一个自己的DBHelper类,继承自OrmLiteSqliteOpenHelper,这个类可以在程序被安装时创建或者升级数据库,同时也可以提供一个DAO给其他的类使用。这个helper类需要实现onCreate(SQLiteDatabase sqliteDatabase, ConnectionSource connectionSource)onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion)方法。一个用于生成数据库,一个用于升级数据库。

继承OrmLiteSqliteOpenHelper类,自定义数据库辅助类DBHelper.class

public class DBHelper extends OrmLiteSqliteOpenHelper {
    /**
     * 数据库名字
     */
    private static final String DB_NAME = "ormlite.db";

    /**
     * 数据库版本
     */
    private static final int DB_VERSION = 1;

    /**
     * 用来存放Dao的Map集合,之所以创建Map集合,是为了方便对数据库资源的管理
     */
    private Map<String, Dao> daos = new HashMap<String, Dao>();

    /**
     * 数据库连接对象
     */
    private AndroidConnectionSource connectionSource;

    /**
     * 单例对象
     */
    private static DBHelper instance;

    /**
     * <p>Title: DBHelper</p>
     * <p>Description: 构造方法</p>
     *
     * @param context         上下文资源
     * @param databaseName    数据库名称
     * @param factory         游标工厂
     * @param databaseVersion 数据库版本
     */
    public DBHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

    /**
     * @param context
     * @return DBHelper
     * @Title: getHelper
     * @Description: TODO(使用单例模式获取数据库对象)
     */
    public static synchronized DBHelper getHelper(Context context) {
        if (instance == null) {
            synchronized (DBHelper.class) {
                if (instance == null) {
                    instance = new DBHelper(context);
                }
            }
        }
        return instance;
    }

    /**
     * @param cls
     * @return dao
     * @Title: getDao
     * @Description: TODO(通过类名获得指定的Dao,并将取得的Dao放入Map集合)
     */
    public synchronized Dao getDao(Class cls) throws SQLException {
        Dao dao = null;
        // 获得类名
        String className = cls.getSimpleName();
        // 判断类名是否为空
        if (!className.equals("") || !className.equals(null)) {
            // 如果不为空则获取Dao对象
            dao = super.getDao(cls);
            // 将Dao对象放入Map集合
            daos.put(className, dao);
        } else {
            return null;
        }
        return dao;
    }

    /* (non-Javadoc)
     * @see com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper#onCreate(android.database.sqlite.SQLiteDatabase, com.j256.ormlite.support.ConnectionSource)
     */
    @Override
    public void onCreate(SQLiteDatabase sqliteDatabase, ConnectionSource connectionSource) {
        // 创建操作
        try {
            // 创建用户表
            TableUtils.createTable(connectionSource, User.class);
            // 创建文章表
            TableUtils.createTable(connectionSource, Article.class);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /* (non-Javadoc)
     * @see com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper#onUpgrade(android.database.sqlite.SQLiteDatabase,
                com.j256.ormlite.support.ConnectionSource, int, int)
     */
    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource, int oldVersion,
                          int newVersion) {
        // 更新操作
        try {
            // 更新用户表
            TableUtils.dropTable(connectionSource, User.class, true);
            // 更新文章表
            TableUtils.dropTable(connectionSource, Article.class, true);
            onCreate(sqLiteDatabase, connectionSource);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * @Title: close
     * @Description: TODO(释放资源)
     */
    public void close() {
        super.close();
        for (String key : daos.keySet()) {
            Dao dao = daos.get(key);
            // 释放Dao资源
            dao = null;
        }
    }
}

(四)创建DAO

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

    /**
     *
     * <p>Title: UserDao</p>
     * <p>Description: 构造方法</p>
     * @param context  上下午资源对象
     */
    public UserDao(Context context) {
        try {
            // 使用单例模式
            dbHelper = DBHelper.getHelper(context);
            userDao = dbHelper.getDao(User.class);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * @Title: add
     * @Description: TODO(添加用户)
     * @param  user
     * @return void
     */
    public void add(User user) {
        try {
            userDao.create(user);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * @Title: delete
     * @Description: TODO(根据ID删除单条记录)
     * @param  id
     * @return void
     */
    public void delete(int id) {
        try {
            userDao.deleteById(id);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     *
     * @Title: update
     * @Description: TODO(更新单条记录)
     * @param  user
     * @return void
     */
    public void update(User user) {
        try {
            userDao.createOrUpdate(user);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * @Title: queryForId
     * @Description: TODO(根据ID查询单条记录)
     * @param  id
     * @return User
     */
    public User queryForId(int id) {
        User user = null;
        try {
            user = userDao.queryForId(id);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return user;
    }

    /**
     * @Title: queryForAll
     * @Description: TODO(查询所有记录)
     * @return List<User>
     */
    public List<User> queryForAll() {
        List<User> mUsers = new ArrayList<User>();
        try {
            mUsers = userDao.queryForAll();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return mUsers;
    }
}

DAO里的主要方法:

  • create 插入一条数据
  • createIfNotExists 如果不存在则插入
  • createOrUpdate 如果指定id则更新
  • queryForId 更具id查找
  • update 查找出数据
  • delete 删除数据
  • queryBuilder() 创建一个查询生成器:进行复杂查询
  • deleteBuilder() 创建一个删除生成器,进程复杂条件删除
  • updateBuilder() 创建修条件生成器,进行复杂条件修改

(五)数据增删改查

public class MainActivity extends Activity implements OnClickListener {

    private TextView tv_show;      // 控制台显示文本
    private Button btn_add;          // 新增
    private Button btn_query;          // 查询
    private Button btn_update;          // 更新
    private Button btn_delete;          // 删除
    private User user;
    private UserDao userDao;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        userDao = new UserDao(this);
        // 实例化控件
        init();
        // 设置监听事件
        setListener();
    }

    /**
     * @param
     * @return void
     * @Title: init
     * @Description: TODO(实例化控件)
     */
    private void init() {
        tv_show = (TextView) findViewById(R.id.tv_show);
        btn_add = (Button) findViewById(R.id.btn_add);
        btn_query = (Button) findViewById(R.id.btn_query);
        btn_update = (Button) findViewById(R.id.btn_update);
        btn_delete = (Button) findViewById(R.id.btn_delete);
    }

    /**
     * @param
     * @return void
     * @Title: setListener
     * @Description: TODO(设置监听事件)
     */
    private void setListener() {
        btn_add.setOnClickListener(this);
        btn_query.setOnClickListener(this);
        btn_update.setOnClickListener(this);
        btn_delete.setOnClickListener(this);
    }

    /* (non-Javadoc)
     * @see android.view.View.OnClickListener#onClick(android.view.View)
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            // 新增操作
            case R.id.btn_add:
                add();
                break;
            // 查询操作
            case R.id.btn_query:
                query();
                break;
            // 更新操作
            case R.id.btn_update:
                update();
                break;
            // 删除操作
            case R.id.btn_delete:
                delete();
                break;

            default:
                break;
        }
    }

    /**
     * @param
     * @return void
     * @Title: add
     * @Description: TODO(添加数据)
     */
    private void add() {
        for (int i = 1; i <= 10; i++) {
            user = new User();
            user.setName("Alonez_" + i);   // 设置姓名
            user.setAge(10 + i);        // 设置年龄
            userDao.add(user);
        }
        tv_show.setText("新增了" + userDao.queryForAll().size() + "位用户\n第1位用户名为:" +
                userDao.queryForAll().get(0).getName() +
                "\n" + "第" + userDao.queryForAll().size() + "位用户名为:" +
                "" + userDao.queryForAll().get(userDao.queryForAll().size() - 1).getName());
    }

    /**
     * @param
     * @return void
     * @Title: query
     * @Description: TODO(查询数据)
     */
    private void query() {
        user = userDao.queryForId(5);
        tv_show.setText("第5位用户ID:" + user.getId() + "\n"
                + "第5位用户姓名:" + user.getName() + "\n"
                + "第5位用户年龄:" + user.getAge() + "\n"
                + "第5位用户描述:" + user.getDesc());
    }

    /**
     * @param
     * @return void
     * @Title: update
     * @Description: TODO(更新操作)
     */
    private void update() {
        user = new User();
        user.setId(5);
        user.setName("我是第5位用户");
        user.setAge(77);
        user.setDesc("啦啦啦,德玛西亚");
        userDao.update(user);

        user = userDao.queryForId(5);
        tv_show.setText("第5位用户ID:" + user.getId() + "\n"
                + "第5位用户姓名:" + user.getName() + "\n"
                + "第5位用户年龄:" + user.getAge() + "\n"
                + "第5位用户描述:" + user.getDesc());
    }

    /**
     * @param
     * @return void
     * @Title: delete
     * @Description: TODO(删除操作)
     */
    private void delete() {
        userDao.delete(1);
        tv_show.setText("数据库还有" + userDao.queryForAll().size() + "位用户");
    }
}

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.sence.testormlite.MainActivity"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_show"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="17dp"
        android:text="显示文本"/>

    <Button
        android:id="@+id/btn_add"
        android:layout_marginTop="40dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="创建十条数据"/>
    <Button
        android:id="@+id/btn_query"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="查询一条数据"/>
    <Button
        android:id="@+id/btn_update"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="更新一条数据"/>
    <Button
        android:id="@+id/btn_delete"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="删除一条数据"/>
</LinearLayout>

这章内容到这里就要结束了,后期还会继续更其他数据库框架的内容,当然最后会作一期对比总结版,じゃ、みんな、さようなら。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值