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

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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

    类这么定义:

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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类暂且就两个属性:

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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
    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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. }  

    接下来看我们的测试类:
    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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、即上述写法

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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的代码:

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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.     }  

    测试代码:
    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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.     }  
    输出:
    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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 

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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、更复杂的查询

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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中直接写如下代码:

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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官方文档,源码中也会提供~~

    源码点击下载

  • 相关阅读:
    48. Rotate Image
    83. Remove Duplicates from Sorted List
    46. Permutations
    HTML5笔记
    18. 4Sum
    24. Swap Nodes in Pairs
    42. Trapping Rain Water
    Python modf() 函数
    Python min() 函数
    Python max() 函数
  • 原文地址:https://www.cnblogs.com/xgjblog/p/6561032.html
Copyright © 2011-2022 走看看