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

75 篇文章 1 订阅
28 篇文章 0 订阅

效果图:


项目包结构如下:


步骤:

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 {

	@Override
	public 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;
	@Override
	protected 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() {

			@Override
			public void onClick(View v) {
				insertData();
			}
		});
		findViewById(R.id.btn_query).setOnClickListener(new OnClickListener() {

			@Override
			public 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 bean
				Class<?> 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.insert
		ContentValues 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.getColumnIndex
			int 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;
	}

	@Override
	public 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();
	}

	@Override
	public 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();
	}

	@Override
	public 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;
	}

	@Override
	public 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);
	}

	@Override
	public 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();
	}

	@Override
	public 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>


整理自教程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值