zoukankan      html  css  js  c++  java
  • Android 数据库框架OrmLite的使用(二)

    前面说了OrmLite的基本使用,现在说下更规范的做法以及常用的一些功能。

    1.DatabaseHelper

    package com.example.ormlite.db;
    import java.sql.SQLException;
    import java.util.HashMap;
    import java.util.Map;
    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteDatabase.CursorFactory;
    import com.example.ormlite.bean.Article;
    import com.example.ormlite.bean.User;
    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;
    /**
     * 1.整个DatabaseHelper使用单例只对外公布一个对象,保证app中只存在一个SQLite Connection,参考文章:http://www.touchlab.co/2011/10/single-sqlite-connection/
     * 2.对每个Bean创建一个XXXDao来处理当前Bean的数据库操作,当然真正去和数据库打交道的对象,通过getDao(T t)进行获取
     *      getDao为一个泛型方法,会根据传入的Class对象进行创建Dao,并且用一个Map来保存对所有的Dao对象,只有第一次调用时才会去调用底层的getDao()。
     * @author Administrator
     *
     */
    public class DatabaseHelperTwo extends OrmLiteSqliteOpenHelper{
        
        private static final String TABLE_NAME="sqlite-test.db";
        private static DatabaseHelperTwo instance;
        
        private Map<String,Dao> daos=new HashMap<String,Dao>();
        public DatabaseHelperTwo(Context context) {
            super(context, TABLE_NAME, null, 4);
        }
        @Override
        public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) {
            try {
                TableUtils.createTable(connectionSource, User.class);
                TableUtils.createTable(connectionSource, Article.class);
    //            TableUtils.createTable(connectionSource, Student.class);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion,
                int newVersion) {
            try {
                TableUtils.dropTable(connectionSource, User.class, true);
                TableUtils.dropTable(connectionSource, Article.class, true);
    //            TableUtils.dropTable(connectionSource, Student.class, true);
                onCreate(database, connectionSource);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        
        /**
         * 单例获取该Helper
         * @param context
         * @return
         */
        public static synchronized DatabaseHelperTwo getHelper(Context context){
            context=context.getApplicationContext();
            if(instance==null){
                synchronized(DatabaseHelperTwo.class){
                    if(instance==null){
                        instance=new DatabaseHelperTwo(context);
                    }
                }
            }
            return instance;
        }
        
        public synchronized Dao getDao(Class clazz) throws SQLException{
            Dao dao=null;
            String className=clazz.getSimpleName();
            if(daos.containsKey(className)){
                dao=daos.get(className);
            }
            if(dao==null){
                dao=super.getDao(clazz);
                daos.put(className, dao);
            }
            return dao;
        }
        
        /**
         * 释放资源
         */
        @Override
        public void close() {
            super.close();
            for (String key : daos.keySet()) {
                Dao dao=daos.get(key);
                dao=null;
            }
        }
    }

    2.编写Dao类

    package com.example.ormlite.dao;
    import java.sql.SQLException;
    import com.example.ormlite.bean.User;
    import com.example.ormlite.db.DatabaseHelperTwo;
    import com.j256.ormlite.dao.Dao;
    import android.content.Context;
    
    public class UserDaoTwo {
        private Context context;
        private Dao<User,Integer> userDaoImpl;
        private DatabaseHelperTwo helper;
        
        @SuppressWarnings("unchecked")
        public UserDaoTwo(Context context){
            this.context=context;
            try {
                helper=DatabaseHelperTwo.getHelper(context);
                userDaoImpl=helper.getDao(User.class);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        
        public void add(User user){
            try {
                userDaoImpl.create(user);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        //......other operations
    }

    3.外键引用

    package com.example.ormlite.bean;
    import com.j256.ormlite.field.DatabaseField;
    import com.j256.ormlite.table.DatabaseTable;
    /**
     * ORMLite外键引用
     * 需求:两个表User,Article,其中Article中需要存储User的主键作为关联,在ORMLite中如何实现?
     * 直接在Article中声明一个Int类型userId属性,当作普通属性处理搞定,也是可行的。但是并没有体现面向对象的思想。
     * 可按如下实现:
     * 1.不去定义一个int类型的userId,而是直接定义一个User成员变量,表示本Article属于该User。
     * 2.在User user属性上添加:@DatabaseField(canBeNull=true,foreign=true,columnName="user_id")
     *      canBeNull--表示不能为null;foreign=true表示一个外键;columnName列名
     * @author Administrator
     *
     */
    @DatabaseTable(tableName="tb_article")
    public class Article {
        @DatabaseField(generatedId=true)
        private int id;
        @DatabaseField(columnName="title")
        private String title;
        @DatabaseField(canBeNull=true,foreign=true,columnName="user_id")
        private User user;
        public Article() {
            super();
            // TODO Auto-generated constructor stub
        }
        public Article(String title, User user) {
            super();
            this.title = title;
            this.user = user;
        }
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getTitle() {
            return title;
        }
        public void setTitle(String title) {
            this.title = title;
        }
        public User getUser() {
            return user;
        }
        public void setUser(User user) {
            this.user = user;
        }
        @Override
        public String toString() {
            return "Article [id=" + id + ", title=" + title + ", user=" + user
                    + "]";
        }
    }

    接下来编写ArticleDao:

    package com.example.ormlite.dao;
    import java.sql.SQLException;
    import java.util.List;
    import android.content.Context;
    import com.example.ormlite.bean.Article;
    import com.example.ormlite.bean.User;
    import com.example.ormlite.db.DatabaseHelperTwo;
    import com.j256.ormlite.dao.Dao;
    
    public class ArticleDao {
        private Dao<Article,Integer> articleDaoImpl;
        private DatabaseHelperTwo helper;
        
        @SuppressWarnings("unchecked")
        public ArticleDao(Context context){
            helper=DatabaseHelperTwo.getHelper(context);
            try {
                articleDaoImpl=helper.getDao(Article.class);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        
        /**
         * 添加
         * @param article
         */
        public void add(Article article){
            try {
                articleDaoImpl.create(article);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        
        /**
         * 通过Id得到一个Article
         * @param id
         * @return
         */
        @SuppressWarnings("unchecked")
        public Article getArticleWithUser(int id){
            Article article=null;
            try {
                article=articleDaoImpl.queryForId(id);
                //如何做到只传一个Article的id,然后能够拿到Article对象,且内部的user属性直接赋值?
                //方式1
                helper.getDao(User.class).refresh(article.getUser());
                //方式2
                //在user属性的注解上:@DatabaseField(canBeNull = true, foreign = true, columnName = "user_id", foreignAutoRefresh = true)
                //foreignAutoRefresh =true,当调用queryForId时,拿到Article对象则直接携带了user
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return article;
        }
        
        /**
         * 通过Id得到一片文章
         * @param id
         * @return
         */
        public Article getArticleById(int id){
            Article article=null;
            try {
                article=articleDaoImpl.queryForId(id);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return article;
        }
        
        public List<Article> getArticleListByUserId(int userId){
            try {
                return articleDaoImpl.queryBuilder().where().eq("user_id", userId).query();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    测试:

    package com.example.ormlite.test;
    import java.util.List;
    import android.test.AndroidTestCase;
    import android.util.Log;
    import com.example.ormlite.bean.Article;
    import com.example.ormlite.bean.User;
    import com.example.ormlite.dao.ArticleDao;
    import com.example.ormlite.dao.UserDao;
    import com.example.ormlite.dao.UserDaoTwo;
    
    public class OrmLiteDbTestTwo extends AndroidTestCase{
        public void AddArticle(){
            User u=new User();
            u.setName("yq");
            u.setDesc("developer");
            new UserDao(getContext()).add(u);
            
            Article article=new Article();
            article.setTitle("ORMLite的使用");
            article.setUser(u);
            new ArticleDao(getContext()).add(article);
        }
        
        public void testGetArticleById(){
            Article article = new ArticleDao(getContext()).getArticleById(1);
            Log.i("OrmLiteDbTestTwo", article.getUser().toString() + " , " + article.getTitle());
        }
        
        /**
         * 通过id获取一个携带User的Article
         */
        public void testGetArticleWithUser(){
            Article article = new ArticleDao(getContext()).getArticleWithUser(1);
            Log.i("OrmLiteDbTestTwo", article.getUser().toString() + " , " + article.getTitle());
        }
        
        public void testSGetArticleListByUserId(){
            List<Article> articles =new ArticleDao(getContext()).getArticleListByUserId(1);
            Log.i("OrmLiteDbTestTwo", articles.toString());
        }
    }

    4.关联一个集合

    每个User关联一个或多个Article,如果在User中声明一个Collection<Article> articles,可否做到在查询User的时候一并能够获取到articles的值?

    是可以的。在User中加属性:

    @ForeignCollectionField
    private Collection<Article> articles;

    UserDao中加方法:

    public User getUserById(int id){
            try {
                return userDaoImpl.queryForId(id);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }

    测试中加方法:

    public void testGetUserById(){
            User user=new UserDaoTwo(getContext()).getUserById(2);
            Log.i("OrmLiteDbTestTwo", user.getName());
            if(user.getArticles()!=null){
                for (Article article : user.getArticles()) {
                    Log.i("OrmLiteDbTestTwo", article.toString());
                }
            }
        }

    5.查询条件QueryBuilder的使用

    (1)简单的where等于

    articleDaoImpl.queryBuilder().where().eq("user_id", userId).query(); //返回Article的列表

    (2)where and 

    QueryBuilder<Article, Integer> queryBuilder=articleDaoImpl.queryBuilder();
                Where<Article, Integer> where=queryBuilder.where();
                where.eq("user_id", 2);
                where.and();
                where.eq("name", "xxx");
                
                //或者
                articleDaoImpl.queryBuilder().where().eq("user_id", userId).and().eq("name", "xxx");

    上述的两种方法都相当于:select * from tb_article where user_id = 2 and name = 'xxx' ; 

    (3)复杂查询

    where.or(
                        where.and(
                                where.eq("user_id", 1),where.eq("name", "xxx")),
                        where.and(
                                where.eq("user_id", 2),where.eq("name", "yyy")));

    select * from tb_article where ( user_id = 1 and name = 'xxx' )  or ( user_id = 2 and name = 'yyy' )  ;

    再复杂的查询也可通过拼凑获得。

    6.updateBuilder、deleteBuilder

    使用queryBuilder是我们希望查询完后直接返回List<Bean>集合,对于update我们并不关注返回值,可以直接用articleDaoImpl.updateRaw(statement, arguments);传入sql和参数即可。也就没必要去用

    articleDaoImpl.updateBuilder().updateColumnValue("name","zzz").where().eq("user_id", 1);这么痛苦了。

    同理,deleteBuilder也建议直接瓶邪sql,当然很简单的除外。

    7.事务

    在Dao中直接写如下代码:

    TransactionManager.callInTransaction(helper.getConnectionSource(),
                        new Callable<Void>() {
    
                            @Override
                            public Void call() throws Exception {
    
                                return null;
                            }
                        });

    8.其他操作

    1.当Bean继承BaseDaoEnable时,可以使用bean.create(bean); bean.update(bean)一类操作

    例如:

    package com.example.ormlite.bean;
    import com.j256.ormlite.field.DatabaseField;
    import com.j256.ormlite.misc.BaseDaoEnabled;
    import com.j256.ormlite.table.DatabaseTable;
    
    @DatabaseTable(tableName = "tb_student")
    public class Student extends BaseDaoEnabled<Student, Integer>
    {
        @DatabaseField(generatedId = true)
        private int id;
    
        @DatabaseField
        private String name;
        
        public Student(){
        }
    
        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;
        }
    }
    Dao dao=DatabaseHelperTwo.getHelper(context).getDao(Student.class);
                Student stu=new Student();
                stu.setDao(dao);
                stu.setName("qq");
                stu.create();

    前提是dao需要手动设置,如果dao为null会报错。

    2.Join

    Article与User做Join操作:

    QueryBuilder<Article, Integer> articleBuilder = articleDaoImpl.queryBuilder();  
                QueryBuilder userBuilder = helper.getDao(User.class).queryBuilder();  
                articleBuilder.join(userBuilder); 

    其他具体的查看官方文档。

    源码下载:http://pan.baidu.com/s/1ntMX99n 提取码:jri5

  • 相关阅读:
    Delphi实战中讲解FormCreate,FormShow,FormActivate
    delphi Try except on e:Exception do
    Delphi处理数据网格DBGrid的编辑框 获取还没有提交到数据集的字段文本
    delphi dbgrid中如何自动生成序号
    DBDateTimePicker;
    Delphi控件开发浅入深出(八)
    delphi中日期类型TDateTime使用总结
    在DBGrid录数据时,如何判断光标位置是在数据的最左或最右,如果是最左或最右则在按左右光标键时光标跳到上一格或下一格,如果是在数据中
    请问如何按Enter键让DBGrid的光标向右移以及换行?(0分)
    tdbgrid中用enter仿真tab键盘_delphi教程
  • 原文地址:https://www.cnblogs.com/Joanna-Yan/p/5001279.html
Copyright © 2011-2022 走看看