效果图:
项目包结构如下:
步骤:
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>
整理自教程