zoukankan      html  css  js  c++  java
  • Android 快速开发系列 ORMLite 框架最佳实践

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/39122981,本文出自【张鸿洋的博客】

    上一篇已经对ORMLite框架做了简单的介绍:Android ORMLite 框架的入门用法~~本篇将介绍项目可能会使用到的一些用法,也为我们的使用ORMLite框架总结出一个较合理的用法。

    通过上一篇的了解,我们使用ORMLite,需要自己写一个DatabaseHelper去继承OrmLiteSqliteOpenHelper,下面我们首先给出一个我认为比较靠谱的Helper的写法:

    1、DatabaseHelper

    1. package com.zhy.zhy_ormlite.db;  
    2.   
    3. import java.sql.SQLException;  
    4. import java.util.HashMap;  
    5. import java.util.Map;  
    6.   
    7. import android.content.Context;  
    8. import android.database.sqlite.SQLiteDatabase;  
    9.   
    10. import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;  
    11. import com.j256.ormlite.dao.Dao;  
    12. import com.j256.ormlite.support.ConnectionSource;  
    13. import com.j256.ormlite.table.TableUtils;  
    14. import com.zhy.zhy_ormlite.bean.Article;  
    15. import com.zhy.zhy_ormlite.bean.Student;  
    16. import com.zhy.zhy_ormlite.bean.User;  
    17.   
    18. public  class DatabaseHelper extends OrmLiteSqliteOpenHelper  
    19. {  
    20.     private static final String TABLE_NAME = "sqlite-test.db";  
    21.   
    22.     private Map<String, Dao> daos = new HashMap<String, Dao>();  
    23.   
    24.     private DatabaseHelper(Context context)  
    25.     {  
    26.         super(context, TABLE_NAME, null, 4);  
    27.     }  
    28.   
    29.     @Override  
    30.     public void onCreate(SQLiteDatabase database,  
    31.             ConnectionSource connectionSource)  
    32.     {  
    33.         try  
    34.         {  
    35.             TableUtils.createTable(connectionSource, User.class);  
    36.             TableUtils.createTable(connectionSource, Article.class);  
    37.             TableUtils.createTable(connectionSource, Student.class);  
    38.         } catch (SQLException e)  
    39.         {  
    40.             e.printStackTrace();  
    41.         }  
    42.     }  
    43.   
    44.     @Override  
    45.     public void onUpgrade(SQLiteDatabase database,  
    46.             ConnectionSource connectionSource, int oldVersion, int newVersion)  
    47.     {  
    48.         try  
    49.         {  
    50.             TableUtils.dropTable(connectionSource, User.class, true);  
    51.             TableUtils.dropTable(connectionSource, Article.class, true);  
    52.             TableUtils.dropTable(connectionSource, Student.class, true);  
    53.             onCreate(database, connectionSource);  
    54.         } catch (SQLException e)  
    55.         {  
    56.             e.printStackTrace();  
    57.         }  
    58.     }  
    59.   
    60.     private static DatabaseHelper instance;  
    61.   
    62.     /** 
    63.      * 单例获取该Helper 
    64.      *  
    65.      * @param context 
    66.      * @return 
    67.      */  
    68.     public static synchronized DatabaseHelper getHelper(Context context)  
    69.     {  
    70.         context = context.getApplicationContext();  
    71.         if (instance == null)  
    72.         {  
    73.             synchronized (DatabaseHelper.class)  
    74.             {  
    75.                 if (instance == null)  
    76.                     instance = new DatabaseHelper(context);  
    77.             }  
    78.         }  
    79.   
    80.         return instance;  
    81.     }  
    82.   
    83.     public synchronized Dao getDao(Class clazz) throws SQLException  
    84.     {  
    85.         Dao dao = null;  
    86.         String className = clazz.getSimpleName();  
    87.   
    88.         if (daos.containsKey(className))  
    89.         {  
    90.             dao = daos.get(className);  
    91.         }  
    92.         if (dao == null)  
    93.         {  
    94.             dao = super.getDao(clazz);  
    95.             daos.put(className, dao);  
    96.         }  
    97.         return dao;  
    98.     }  
    99.   
    100.     /** 
    101.      * 释放资源 
    102.      */  
    103.     @Override  
    104.     public void close()  
    105.     {  
    106.         super.close();  
    107.   
    108.         for (String key : daos.keySet())  
    109.         {  
    110.             Dao dao = daos.get(key);  
    111.             dao = null;  
    112.         }  
    113.     }  
    114.   
    115. }  


    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()。

    2、Bean的Dao

    1. package com.zhy.zhy_ormlite.db;  
    2.   
    3. import java.sql.SQLException;  
    4.   
    5. import android.content.Context;  
    6.   
    7. import com.j256.ormlite.dao.Dao;  
    8. import com.zhy.zhy_ormlite.bean.User;  
    9.   
    10. public class UserDao  
    11. {  
    12.     private Context context;  
    13.     private Dao<User, Integer> userDaoOpe;  
    14.     private DatabaseHelper helper;  
    15.   
    16.     public UserDao(Context context)  
    17.     {  
    18.         this.context = context;  
    19.         try  
    20.         {  
    21.             helper = DatabaseHelper.getHelper(context);  
    22.             userDaoOpe = helper.getDao(User.class);  
    23.         } catch (SQLException e)  
    24.         {  
    25.             e.printStackTrace();  
    26.         }  
    27.     }  
    28.   
    29.     /** 
    30.      * 增加一个用户 
    31.      * @param user 
    32.      */  
    33.     public void add(User user)  
    34.     {  
    35.         try  
    36.         {  
    37.             userDaoOpe.create(user);  
    38.         } catch (SQLException e)  
    39.         {  
    40.             e.printStackTrace();  
    41.         }  
    42.   
    43.     }//...other operations  
    44.   
    45.   
    46. }  


    我们的所有的XXXDao遵循以上的风格~

    好了,基本了解了我们的代码的结构~~ps:如果觉得不合理可以留言指出,如果觉得不能接收,直接忽略。。。

    3、ORMLite外键引用

    现在我们有两张表一张User,一张Article; 

    Article中当然需要存储User的主键,作为关联~~那么在ORMLite中如何做到呢?

    可能有人会直接在Article中声明一个int类型userId属性,当作普通属性处理搞定,这种做法并没有做,但是没有体现出面向对象的思想。

    面向对象是这样的:Article属于某个User

    类这么定义:

    1. package com.zhy.zhy_ormlite.bean;  
    2.   
    3. import com.j256.ormlite.field.DatabaseField;  
    4. import com.j256.ormlite.table.DatabaseTable;  
    5.   
    6. @DatabaseTable(tableName = "tb_article")  
    7. public class Article  
    8. {  
    9.     @DatabaseField(generatedId = true)  
    10.     private int id;  
    11.     @DatabaseField  
    12.     private String title;  
    13.     @DatabaseField(canBeNull = true, foreign = true, columnName = "user_id")  
    14.     private User user;  
    15.   
    16.     public int getId()  
    17.     {  
    18.         return id;  
    19.     }  
    20.   
    21.     public void setId(int id)  
    22.     {  
    23.         this.id = id;  
    24.     }  
    25.   
    26.     public String getTitle()  
    27.     {  
    28.         return title;  
    29.     }  
    30.   
    31.     public void setTitle(String title)  
    32.     {  
    33.         this.title = title;  
    34.     }  
    35.   
    36.     public User getUser()  
    37.     {  
    38.         return user;  
    39.     }  
    40.   
    41.     public void setUser(User user)  
    42.     {  
    43.         this.user = user;  
    44.     }  
    45.   
    46.     @Override  
    47.     public String toString()  
    48.     {  
    49.         return "Article [id=" + id + ", title=" + title + ", user=" + user  
    50.                 + "]";  
    51.     }  
    52.   
    53. }  


    不会去定义一个int类型的userId,而是直接定义一个User成员变量,表示本Article属于该User;

    然后在User user属性上添加: @DatabaseField(canBeNull = true, foreign = true, columnName = "user_id")

    canBeNull -表示不能为null;foreign=true表示是一个外键;columnName 列名

    User类暂且就两个属性:

    1. package com.zhy.zhy_ormlite.bean;  
    2.   
    3. import com.j256.ormlite.field.DatabaseField;  
    4. import com.j256.ormlite.table.DatabaseTable;  
    5.   
    6. @DatabaseTable(tableName = "tb_user")  
    7. public class User   
    8. {  
    9.     @DatabaseField(generatedId = true)  
    10.     private int id;  
    11.     @DatabaseField(columnName = "name")  
    12.     private String name;  
    13.   
    14.   
    15.     public User()  
    16.     {  
    17.     }  
    18.   
    19.     public int getId()  
    20.     {  
    21.         return id;  
    22.     }  
    23.   
    24.     public void setId(int id)  
    25.     {  
    26.         this.id = id;  
    27.     }  
    28.   
    29.     public String getName()  
    30.     {  
    31.         return name;  
    32.     }  
    33.   
    34.     public void setName(String name)  
    35.     {  
    36.         this.name = name;  
    37.     }  
    38.   
    39.     @Override  
    40.     public String toString()  
    41.     {  
    42.         return "User [id=" + id + ", name=" + name   
    43.                 + "]";  
    44.     }  
    45.   
    46.       
    47.   
    48.   
    49.       
    50. }  


    现在看我们的ArticleDao

    1. package com.zhy.zhy_ormlite.db;  
    2.   
    3. import java.sql.SQLException;  
    4. import java.util.List;  
    5.   
    6. import android.content.Context;  
    7.   
    8. import com.j256.ormlite.dao.Dao;  
    9. import com.zhy.zhy_ormlite.bean.Article;  
    10. import com.zhy.zhy_ormlite.bean.User;  
    11.   
    12. public class ArticleDao  
    13. {  
    14.     private Dao<Article, Integer> articleDaoOpe;  
    15.     private DatabaseHelper helper;  
    16.   
    17.     @SuppressWarnings("unchecked")  
    18.     public ArticleDao(Context context)  
    19.     {  
    20.         try  
    21.         {  
    22.             helper = DatabaseHelper.getHelper(context);  
    23.             articleDaoOpe = helper.getDao(Article.class);  
    24.         } catch (SQLException e)  
    25.         {  
    26.             e.printStackTrace();  
    27.         }  
    28.     }  
    29.   
    30.     /** 
    31.      * 添加一个Article 
    32.      * @param article 
    33.      */  
    34.     public void add(Article article)  
    35.     {  
    36.         try  
    37.         {  
    38.             articleDaoOpe.create(article);  
    39.         } catch (SQLException e)  
    40.         {  
    41.             e.printStackTrace();  
    42.         }  
    43.     }  
    44.   
    45.     /** 
    46.      * 通过Id得到一个Article 
    47.      * @param id 
    48.      * @return 
    49.      */  
    50.     @SuppressWarnings("unchecked")  
    51.     public Article getArticleWithUser(int id)  
    52.     {  
    53.         Article article = null;  
    54.         try  
    55.         {  
    56.             article = articleDaoOpe.queryForId(id);  
    57.             helper.getDao(User.class).refresh(article.getUser());  
    58.   
    59.         } catch (SQLException e)  
    60.         {  
    61.             e.printStackTrace();  
    62.         }  
    63.         return article;  
    64.     }  
    65.       
    66.     /** 
    67.      * 通过Id得到一篇文章 
    68.      * @param id 
    69.      * @return 
    70.      */  
    71.     public Article get(int id)  
    72.     {  
    73.         Article article = null;  
    74.         try  
    75.         {  
    76.             article = articleDaoOpe.queryForId(id);  
    77.   
    78.         } catch (SQLException e)  
    79.         {  
    80.             e.printStackTrace();  
    81.         }  
    82.         return article;  
    83.     }  
    84.   
    85.     /** 
    86.      * 通过UserId获取所有的文章 
    87.      * @param userId 
    88.      * @return 
    89.      */  
    90.     public List<Article> listByUserId(int userId)  
    91.     {  
    92.         try  
    93.         {  
    94.             return articleDaoOpe.queryBuilder().where().eq("user_id", userId)  
    95.                     .query();  
    96.         } catch (SQLException e)  
    97.         {  
    98.             e.printStackTrace();  
    99.         }  
    100.         return null;  
    101.     }  
    102.   
    103. }  


    接下来看我们的测试类:

    1. public class OrmLiteDbTest extends AndroidTestCase  
    2. {  
    3.     public void testAddArticle()  
    4.     {  
    5.         User u = new User();  
    6.         u.setName("张鸿洋");  
    7.         new UserDao(getContext()).add(u);  
    8.         Article article = new Article();  
    9.         article.setTitle("ORMLite的使用");  
    10.         article.setUser(u);  
    11.         new ArticleDao(getContext()).add(article);  
    12.   
    13.     }  
    14.   
    15.     public void testGetArticleById()  
    16.     {  
    17.         Article article = new ArticleDao(getContext()).get(1);  
    18.         L.e(article.getUser() + " , " + article.getTitle());  
    19.     }  
    20.   
    21.     public void testGetArticleWithUser()  
    22.     {  
    23.   
    24.         Article article = new ArticleDao(getContext()).getArticleWithUser(1);  
    25.         L.e(article.getUser() + " , " + article.getTitle());  
    26.     }  
    27.       
    28.     public void testListArticlesByUserId()  
    29.     {  
    30.   
    31.         List<Article> articles = new ArticleDao(getContext()).listByUserId(1);  
    32.         L.e(articles.toString());  
    33.     }  


    分别测试,添加一个Article;通过Id获取一个Article;通过Id获取一个Article且携带User;通过userId获取所有的Article;

    主要看第三个:通过Id获取一个Article且携带User,testGetArticleWithUser(id)

    如何值传一个Article的Id,然后能够拿到Article对象,且内部的user属性直接赋值呢?

    两种方式:

    1、即上述写法

    1. article = articleDaoOpe.queryForId(id);  
    2.             helper.getDao(User.class).refresh(article.getUser());  


    2、在user属性的注解上:@DatabaseField(canBeNull = true, foreign = true, columnName = "user_id", foreignAutoRefresh = true)

    添加foreignAutoRefresh =true,这样;当调用queryForId时,拿到Article对象则直接携带了user;

    4、关联一个集合

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

    答案是可以的。在User中添加如下属性,且注解如下:

    @ForeignCollectionField
    private Collection<Article> articles;

    我们在UserDao中书写查询User的代码:

    1. public User get(int id)  
    2.     {  
    3.         try  
    4.         {  
    5.             return userDaoOpe.queryForId(id);  
    6.         } catch (SQLException e)  
    7.         {  
    8.             e.printStackTrace();  
    9.         }  
    10.         return null ;  
    11.     }  


    测试代码:

    1. public void testGetUserById()  
    2.     {  
    3.         User user = new UserDao(getContext()).get(1);  
    4.         L.e(user.getName());  
    5.         if (user.getArticles() != null)  
    6.             for (Article article : user.getArticles())  
    7.             {  
    8.                 L.e(article.toString());  
    9.             }  
    10.     }  

    输出:

    1. 09-07 22:49:06.484: E/zhy(7293): 张鸿洋  
    2. 09-07 22:49:06.484: E/zhy(7293): Article [id=1, title=ORMLite的使用]  

    可以看到,我们通过一个queryForId,成功的获取了User,以及User关联的所有的Articles;

    5、条件查询QueryBuilder的使用

    上述代码其实已经用到了简单的条件查询了:

    1、简单的where等于

    articleDaoOpe.queryBuilder().where().eq("user_id", userId).query();直接返回Article的列表

    2、where and 

    1. QueryBuilder<Article, Integer> queryBuilder = articleDaoOpe  
    2.                 .queryBuilder();  
    3.         Where<Article, Integer> where = queryBuilder.where();  
    4.         where.eq("user_id", 1);  
    5.         where.and();  
    6.         where.eq("name", "xxx");  
    7.   
    8.         //或者  
    9.         articleDaoOpe.queryBuilder().//  
    10.                 where().//  
    11.                 eq("user_id", 1).and().//  
    12.                 eq("name", "xxx");  


    上述两种都相当与:select * from tb_article where user_id = 1 and name = 'xxx' ; 

    3、更复杂的查询

    1. where.or(  
    2.                     //  
    3.                     where.and(//  
    4.                             where.eq("user_id", 1), where.eq("name", "xxx")),  
    5.                     where.and(//  
    6.                             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我们并不关注返回值,直接使用

    articleDaoOpe.updateRaw(statement, arguments);传入sql和参数即可~~

    何必在那articleDaoOpe.updateBuilder().updateColumnValue("name","zzz").where().eq("user_id", 1);这样的痛苦呢~~~

    同理还有deleteBuilder还是建议直接拼写sql,当然很简单的除外,直接使用它的API~

    7、事务操作

    在我们的Dao中直接写如下代码:

    1. //事务操作  
    2.         TransactionManager.callInTransaction(helper.getConnectionSource(),  
    3.                 new Callable<Void>()  
    4.                 {  
    5.   
    6.                     @Override  
    7.                     public Void call() throws Exception  
    8.                     {  
    9.                         return null;  
    10.                     }  
    11.                 });  



    8、其他操作

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

    例如:

    Student extends BaseDaoEnabled<Student, Integer>

    Dao dao = DatabaseHelper.getHelper(getContext()).getDao(Student.class);
    Student student = new Student();
    student.setDao(dao);
    student.setName("张鸿洋");
    student.create();

    前提dao需要手动设置,如果dao为null会报错,尼玛,我觉得一点用没有。。。

    2、Join

    1. QueryBuilder<Article, Integer> articleBuilder = articleDaoOpe  
    2.                     .queryBuilder();  
    3.             QueryBuilder userBuilder = helper.getDao(User.class).queryBuilder();  
    4.             articleBuilder.join(userBuilder);  


    Article与User做Join操作;

    本篇主要想介绍在项目中如何写DataBaseHelper已经如何写BeanDao,以及列出了在项目中可能会用到的ORMLite的功能,如果需要详细了解,还请看ORMLite官方文档,源码中也会提供~~

    源码点击下载

  • 相关阅读:
    [转]开源游戏AI引擎列表与游戏中的人工智能
    [转]刨根问底!曲面细分技术到底是个啥?
    [转]link time code generation
    [转]PythonQt
    [转]Free Game Development Libraries
    Java虚拟机(二):垃圾回收算法 时间
    Java虚拟机(一):JVM的运行机制 时间
    Java虚拟机(四):常用JVM配置参数 时间
    Java虚拟机(三):垃圾收集器 时间
    mov offset和lea的区别
  • 原文地址:https://www.cnblogs.com/wangying222/p/6281896.html
Copyright © 2011-2022 走看看