利用泛型实现一个简单的android orm小例子

来源:互联网 发布:wpf 管理系统源码购 编辑:程序博客网 时间:2024/06/05 16:15

效果图:


项目包结构如下:


步骤:

1、新建一个工程

     2、分析ORM映射

     3、开始分包

     4、创建model

     5、创建表

     6、创建映射文件

     7、定义映射文件对应的类(ORM

     8、通过定义一个模版类,实现动态解析映射文件

     9、插入数据(实现BaseDao里面的插入数据的方法)


具体代码:

MyApplication.java

import com.orm.utils.TemplateConfig;import android.app.Application;public class MyApplication extends Application {@Overridepublic void onCreate() {super.onCreate();// 先初始化xml映射文件TemplateConfig.parseAllXml(this);}}

MainActivity.java

import java.lang.reflect.Constructor;import java.lang.reflect.Method;import java.util.List;import android.app.Activity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import com.orm.utils.Orm;import com.orm.utils.OrmSqliteOpenHelper;import com.orm.utils.TemplateConfig;import com.orm.R;public class MainActivity extends Activity {private EditText et_name;private EditText et_version;    private TextView tv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();}private void initView() {et_name = (EditText) findViewById(R.id.et_name);et_version = (EditText) findViewById(R.id.et_version);        tv = (TextView) findViewById(R.id.tv);findViewById(R.id.btn_insert).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {insertData();}});findViewById(R.id.btn_query).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {queryData();}});}protected void insertData() {// UserDao userDao = new UserDao(new OrmSqliteOpenHelper(this, 1));// try {// long insert = userDao.insert(new User());// if (insert == -1) {// Toast.makeText(this, "插入失败", Toast.LENGTH_LONG).show();// } else {// Toast.makeText(this, "插入成功!---" + insert, Toast.LENGTH_LONG)// .show();// }// } catch (Exception e) {// e.printStackTrace();// }// 获取类名String className = et_name.getText().toString();// 获取数据库更新的版本号int version = Integer.parseInt(et_version.getText().toString());// 获取orm映射Orm orm = TemplateConfig.ormMapping.get(className + ".orm.xml");// 获取dao// 反射try {Class<?> daoClazz = Class.forName(orm.getDaoName());// 思考一个问题:如何获取dao对象?// daoClazz.newInstance()---无参构造创建对象try {// 获取构造方法Constructor<?> constructor = daoClazz.getDeclaredConstructor(new Class[] { OrmSqliteOpenHelper.class });// 获取dao对象Object dao = constructor.newInstance(new OrmSqliteOpenHelper(this, version));// 思考:如何获取java beanClass<?> bean = Class.forName(orm.getBeanName());// 插入数据// 获取插入数据的方法Method insertMethod = daoClazz.getMethod("insert", Object.class);// 执行插入操作long invoke = (Long) insertMethod.invoke(dao,bean.newInstance());if (invoke == -1) {Toast.makeText(this, "插入失败", Toast.LENGTH_LONG).show();} else {Toast.makeText(this, "插入成功!---" + invoke, Toast.LENGTH_LONG).show();}} catch (Exception e) {e.printStackTrace();}} catch (ClassNotFoundException e) {e.printStackTrace();}}protected void queryData() {// 获取类名String className = et_name.getText().toString();// 获取数据库更新的版本号int version = Integer.parseInt(et_version.getText().toString());// 获取orm映射Orm orm = TemplateConfig.ormMapping.get(className + ".orm.xml");try {Class<?> daoClazz = Class.forName(orm.getDaoName());// 获取dao的方法Method method = daoClazz.getMethod("queryAll");// dao对象如何获取// 获取构造方法Constructor<?> constructor = daoClazz.getDeclaredConstructor(new Class[] { OrmSqliteOpenHelper.class });// 获取dao对象Object dao = constructor.newInstance(new OrmSqliteOpenHelper(this,version));// 执行查询方法,返回结果List reult = (List) method.invoke(dao);tv.setText(reult.toString());Log.i("main", reult.toString());} catch (Exception e) {e.printStackTrace();}}}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" >    <EditText        android:id="@+id/et_version"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:text="1" />    <EditText        android:id="@+id/et_name"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:hint="@string/enter_name"        android:text="" />    <Button        android:id="@+id/btn_insert"        android:layout_width="fill_parent"        android:layout_height="wrap_content"         android:text="@string/insert"        android:onClick="insertData" />    <Button        android:id="@+id/btn_query"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:text="@string/query"        android:onClick="queryData" />        <TextView         android:id="@+id/tv"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:padding="2.5dp"        android:textColor="#000000"        android:background="#ffff00"/></LinearLayout>

dao包下的类:

import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List;import android.content.ContentValues;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import com.orm.utils.Item;import com.orm.utils.Key;import com.orm.utils.Orm;import com.orm.utils.OrmSqliteOpenHelper;import com.orm.utils.TemplateConfig;public class BaseDao<T> {private OrmSqliteOpenHelper ormSqliteOpenHelper;private Class<?> clazz;public BaseDao(OrmSqliteOpenHelper ormSqliteOpenHelper, Class<?> clazz) {this.ormSqliteOpenHelper = ormSqliteOpenHelper;this.clazz = clazz;}/** * 插入数据 *  * @param t * @throws ClassNotFoundException * @throws NoSuchMethodException */public long insert(T t) throws Exception {// 1、获取数据库SQLiteDatabase db = this.ormSqliteOpenHelper.getWritableDatabase();// 一般情况直接开干---db.insertContentValues values = new ContentValues();// 动态获取orm映射类Orm orm = TemplateConfig.ormMapping.get(clazz.getSimpleName()+ ".orm.xml");// 常规的方法是这么干的values.put(key, value)// 今天不允许啦// values.put(key, value); ---key代表字段名称// value代表字段对应的值(其实就是这个字段对应的对象的属性的值)// 主键字段Key key = orm.getKey();// 如果主键不自动生成,那么我们需要加入到ContentValues里面if (!key.isIdentity()) {// 反射// 通过反射机制获取ContentValues上的put方法Method method = values.getClass().getDeclaredMethod("put",new Class<?>[] { String.class,Class.forName(key.getType()) });// 获取主键对应的值Field field = t.getClass().getDeclaredField(key.getProperty());// 改变属性的访问权限(设置可以访问)field.setAccessible(true);// 获取属性的值(其实就是获取我们要插入的这个对象上面的属性的值)Object value = field.get(t);// 执行方法put参数method.invoke(values, new Object[] { key.getColumn(), value });}// 普通字段List<Item> items = orm.getItems();for (Item item : items) {Method method = values.getClass().getDeclaredMethod("put",new Class<?>[] { String.class,Class.forName(item.getType()) });// 获取属性值Field field = t.getClass().getDeclaredField(item.getProperty());field.setAccessible(true);Object value = field.get(t);method.invoke(values, new Object[] { item.getColumn(), value });}// 执行插入操作// id代表:执行插入操作的状态(-1:代表插入失败,否者返回影响的行数)long id = db.insert(orm.getTableName(), null, values);return id;}public List<T> queryAll() throws Exception {List<T> list = new ArrayList<T>();// 获取数据库SQLiteDatabase db = ormSqliteOpenHelper.getWritableDatabase();// 获取orm映射对象Orm orm = TemplateConfig.ormMapping.get(clazz.getSimpleName()+ ".orm.xml");Key key = orm.getKey();List<Item> items = orm.getItems();// 查询Cursor cursor = db.query(orm.getTableName(), null, null, null, null,null, null);// 获取cursor类对象Class<? extends Cursor> cursorClazz = cursor.getClass();// 遍历游标while (cursor.moveToNext()) {// 创建对象T t = (T) clazz.newInstance();// 首先获取key(主键)----获取主键的下标cursor.getColumnIndexint keyColumnIndex = cursor.getColumnIndex(key.getColumn());// 思考:现在主键的类型我们知不知道?// ----在这里我们是不知道主键的类型的,所有我们不能够直接从cursor对象上面获取值Method keyMethod = cursorClazz.getMethod(TemplateConfig.cursorMethodMapping.get(key.getType()),int.class);// 获取t对象上面的属性(主键属性)Field keyField = clazz.getDeclaredField(key.getProperty());keyField.setAccessible(true);// 获取方法的值(主键对应的方法的值)Object keyValue = keyMethod.invoke(cursor, keyColumnIndex);// 给key属性设置值keyField.set(t, keyValue);for (Item item : items) {// 获取字段的下标int itemColumnIndex = cursor.getColumnIndex(item.getColumn());Method itemMethod = cursorClazz.getMethod(TemplateConfig.cursorMethodMapping.get(item.getType()),int.class);Field itemField = clazz.getDeclaredField(item.getProperty());itemField.setAccessible(true);Object itemValue = itemMethod.invoke(cursor, itemColumnIndex);itemField.set(t, itemValue);}list.add(t);}db.close();return list;}}

import com.orm.model.User;import com.orm.utils.OrmSqliteOpenHelper;public class UserDao extends BaseDao<User> {public UserDao(OrmSqliteOpenHelper ormSqliteOpenHelper) {super(ormSqliteOpenHelper, User.class);}}


model类:

import java.util.Random;public class User {private int id;private String userName;private int userAge;public User() {super();this.userName = "user_name_" + new Random().nextInt(100000);this.userAge = new Random().nextInt(100);}public User(int id, String userName, int userAge) {super();this.id = id;this.userName = userName;this.userAge = userAge;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public int getUserAge() {return userAge;}public void setUserAge(int userAge) {this.userAge = userAge;}@Overridepublic String toString() {return "User [id=" + id + ", userName=" + userName + ", userAge="+ userAge + "]";}}

utils包:


public class Item {// 映射对应的表字段名称private String column;// 映射对应的类的属性private String property;// 表字段和类属性的类型private String type;public String getColumn() {return column;}public void setColumn(String column) {this.column = column;}public String getProperty() {return property;}public void setProperty(String property) {this.property = property;}public String getType() {return type;}public void setType(String type) {this.type = type;}public Item(String column, String property, String type) {super();this.column = column;this.property = property;this.type = type;}public Item() {super();}@Overridepublic String toString() {return "Key [column=" + column + ", property=" + property + ", type="+ type + "]";}}

public class Key {// 映射对应的表字段名称private String column;// 映射对应的类的属性private String property;// 表字段和类属性的类型private String type;// 是否是主键private boolean identity;public String getColumn() {return column;}public void setColumn(String column) {this.column = column;}public String getProperty() {return property;}public void setProperty(String property) {this.property = property;}public String getType() {return type;}public void setType(String type) {this.type = type;}public boolean isIdentity() {return identity;}public void setIdentity(boolean identity) {this.identity = identity;}public Key(String column, String property, String type, boolean identity) {super();this.column = column;this.property = property;this.type = type;this.identity = identity;}public Key() {super();}@Overridepublic String toString() {return "Key [column=" + column + ", property=" + property + ", type="+ type + ", identity=" + identity + "]";}}

import java.util.ArrayList;import java.util.List;public class Orm {private String tableName;private String beanName;private String daoName;private Key key;private List<Item> items = new ArrayList<Item>();public String getTableName() {return tableName;}public void setTableName(String tableName) {this.tableName = tableName;}public String getBeanName() {return beanName;}public void setBeanName(String beanName) {this.beanName = beanName;}public String getDaoName() {return daoName;}public void setDaoName(String daoName) {this.daoName = daoName;}public Key getKey() {return key;}public void setKey(Key key) {this.key = key;}public List<Item> getItems() {return items;}public void setItems(List<Item> items) {this.items = items;}@Overridepublic String toString() {return "Orm [tableName=" + tableName + ", beanName=" + beanName+ ", daoName=" + daoName + ", key=" + key + ", items=" + items+ "]";}public Orm(String tableName, String beanName, String daoName, Key key,List<Item> items) {super();this.tableName = tableName;this.beanName = beanName;this.daoName = daoName;this.key = key;this.items = items;}public Orm() {super();}}

import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteDatabase.CursorFactory;import android.database.sqlite.SQLiteOpenHelper;public class OrmSqliteOpenHelper extends SQLiteOpenHelper {public static final String DB_NAME = "orm.db";public OrmSqliteOpenHelper(Context context, String name,CursorFactory factory, int version) {super(context, name, factory, version);}public OrmSqliteOpenHelper(Context context, int version) {super(context, DB_NAME, null, version);}@Overridepublic void onCreate(SQLiteDatabase db) {db.beginTransaction();db.execSQL("create table t_user(_tid integer primary key autoincrement, t_user_name varchar(20),t_user_age integer)");db.setTransactionSuccessful();db.endTransaction();}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {if (newVersion == 2) {db.beginTransaction();db.execSQL("create table t_product(_tid integer primary key autoincrement, t_product_name varchar(20),t_product_type varchar(20))");db.setTransactionSuccessful();db.endTransaction();}if (newVersion == 3) {db.beginTransaction();db.execSQL("create table t_product_order(_tid integer primary key autoincrement, t_product_order_name varchar(20),t_product_order_price integer)");db.setTransactionSuccessful();db.endTransaction();}}}

import java.io.IOException;import java.io.InputStream;import java.util.HashMap;import java.util.Map;import org.xmlpull.v1.XmlPullParser;import android.content.Context;import android.content.res.AssetManager;import android.util.Xml;/** * 负责解析映射文件 *  * @author Dream * */public class TemplateConfig {private static final String LABEL_ORM = "orm";private static final String LABEL_KEY = "key";private static final String LABEL_ITEM = "item";private static final String ATTRIBUTE_BEAN_NAME = "beanName";private static final String ATTRIBUTE_DAO_NAME = "daoName";private static final String ATTRIBUTE_TABLE_NAME = "tableName";private static final String ATTRIBUTE_COLUMN = "column";private static final String ATTRIBUTE_IDENTITY = "identity";private static final String ATTRIBUTE_PROPERTY = "property";private static final String ATTRIBUTE_TYPE = "type";public static Map<String, Orm> ormMapping = new HashMap<String, Orm>();public static Map<String, String> cursorMethodMapping = new HashMap<String, String>();static {cursorMethodMapping.put("java.lang.Integer", "getInt");cursorMethodMapping.put("java.lang.String", "getString");cursorMethodMapping.put("java.lang.Float", "getFloat");cursorMethodMapping.put("java.lang.Double", "getDouble");cursorMethodMapping.put("java.lang.Long", "getLong");cursorMethodMapping.put("java.lang.Short", "getShort");}/** * 将所有的映射文件解析出来 *  * @param context */public static void parseAllXml(Context context) {try {AssetManager assetManager = context.getAssets();String[] list = assetManager.list("");for (String file : list) {if (file.endsWith(".orm.xml")) {ormMapping.put(file, parse(assetManager.open(file)));}}} catch (IOException e) {e.printStackTrace();}}public static Orm parse(InputStream inputStream) {Orm orm = null;Key key = null;Item item = null;// xml解析XmlPullParser pullParser = Xml.newPullParser();try {// 设置解析编码格式pullParser.setInput(inputStream, "UTF-8");int eventType = pullParser.getEventType();while (eventType != XmlPullParser.END_DOCUMENT) {String tagName = pullParser.getName();switch (eventType) {case XmlPullParser.START_TAG:if (LABEL_ORM.equals(tagName)) {orm = new Orm();orm.setBeanName(pullParser.getAttributeValue(null,ATTRIBUTE_BEAN_NAME));orm.setDaoName(pullParser.getAttributeValue(null,ATTRIBUTE_DAO_NAME));orm.setTableName(pullParser.getAttributeValue(null,ATTRIBUTE_TABLE_NAME));} else if (LABEL_KEY.equals(tagName)) {key = new Key();key.setColumn(pullParser.getAttributeValue(null,ATTRIBUTE_COLUMN));String attributeValue = pullParser.getAttributeValue(null, ATTRIBUTE_IDENTITY);key.setIdentity(Boolean.parseBoolean(attributeValue));key.setProperty(pullParser.getAttributeValue(null,ATTRIBUTE_PROPERTY));key.setType(pullParser.getAttributeValue(null,ATTRIBUTE_TYPE));orm.setKey(key);} else if (LABEL_ITEM.equals(tagName)) {item = new Item();item.setColumn(pullParser.getAttributeValue(null,ATTRIBUTE_COLUMN));item.setProperty(pullParser.getAttributeValue(null,ATTRIBUTE_PROPERTY));item.setType(pullParser.getAttributeValue(null,ATTRIBUTE_TYPE));orm.getItems().add(item);}break;default:break;}eventType = pullParser.next();}} catch (Exception e) {e.printStackTrace();}return orm;}}

assets目录下的资源文件:

User.orm.xml

<?xml version="1.0" encoding="utf-8"?><!--     tableName:映射的表名 beanName:映射的全类名 daoName:映射的数据访问层的名称--><orm    beanName="com.orm.model.User"    daoName="com.orm.dao.UserDao"    tableName="t_user" >    <key        column="_tid"        identity="true"        property="id"        type="java.lang.Integer" >    </key>    <item        column="t_user_name"        property="userName"        type="java.lang.String">    </item>    <item        column="t_user_age"        property="userAge"        type="java.lang.Integer">    </item></orm>


整理自教程

0 0
原创粉丝点击